|
@@ -1,4 +1,9 @@
|
|
-using Microsoft.EntityFrameworkCore;
|
|
|
|
|
|
+using System.IO;
|
|
|
|
+using System.Security.Cryptography;
|
|
|
|
+
|
|
|
|
+using Microsoft.EntityFrameworkCore;
|
|
|
|
+using Microsoft.EntityFrameworkCore.Infrastructure;
|
|
|
|
+using Microsoft.EntityFrameworkCore.Metadata;
|
|
|
|
|
|
using UniformMaterialManagementSystem.Data;
|
|
using UniformMaterialManagementSystem.Data;
|
|
|
|
|
|
@@ -6,47 +11,65 @@ namespace UniformMaterialManagementSystem.Utils
|
|
{
|
|
{
|
|
public static class DataBaseUtil
|
|
public static class DataBaseUtil
|
|
{
|
|
{
|
|
- public static void ExportTable<T>(string targetConnectionString) where T : class
|
|
|
|
|
|
+ private static readonly string DataBasePath = Environment.CurrentDirectory + "\\DataBase";
|
|
|
|
+ private const string Password = "88384e6a-07e0-47e9-8214-4470a16e78da";
|
|
|
|
+
|
|
|
|
+ public static async void ExportTable<T>(string targetConnectionString) where T : class
|
|
{
|
|
{
|
|
|
|
+ CreateExportFolder();
|
|
|
|
+
|
|
var optionsBuilderSource = new DbContextOptionsBuilder<SqliteContext>();
|
|
var optionsBuilderSource = new DbContextOptionsBuilder<SqliteContext>();
|
|
optionsBuilderSource.UseSqlite("Data Source=UniformMaterialManagementSystem.db");
|
|
optionsBuilderSource.UseSqlite("Data Source=UniformMaterialManagementSystem.db");
|
|
|
|
|
|
|
|
+ var targetPath = $"{DataBasePath}\\UniformMaterialManagementSystem.db";
|
|
|
|
+
|
|
var optionsBuilderTarget = new DbContextOptionsBuilder<SqliteContext>();
|
|
var optionsBuilderTarget = new DbContextOptionsBuilder<SqliteContext>();
|
|
- optionsBuilderTarget.UseSqlite(targetConnectionString);
|
|
|
|
|
|
+ optionsBuilderTarget.UseSqlite($"Data Source={targetPath}");
|
|
|
|
|
|
- using var sourceContext = new SqliteContext(optionsBuilderSource.Options);
|
|
|
|
- using var targetContext = new SqliteContext(optionsBuilderTarget.Options);
|
|
|
|
|
|
+ await using var sourceContext = new SqliteContext(optionsBuilderSource.Options);
|
|
|
|
+ await using var targetContext = new SqliteContext(optionsBuilderTarget.Options);
|
|
|
|
|
|
// 读取源数据
|
|
// 读取源数据
|
|
- var sourceData = sourceContext.Set<T>().ToList();
|
|
|
|
|
|
+ var sourceData = await sourceContext.Set<T>()
|
|
|
|
+ .IncludeAll()
|
|
|
|
+ .ToListAsync();
|
|
|
|
|
|
// 确保目标数据库创建
|
|
// 确保目标数据库创建
|
|
- targetContext.Database.EnsureCreated();
|
|
|
|
|
|
+ await targetContext.Database.MigrateAsync();
|
|
|
|
|
|
// 获取目标 DbSet
|
|
// 获取目标 DbSet
|
|
var targetDbSet = targetContext.Set<T>();
|
|
var targetDbSet = targetContext.Set<T>();
|
|
|
|
|
|
// 添加到目标数据库
|
|
// 添加到目标数据库
|
|
targetDbSet.AddRange(sourceData);
|
|
targetDbSet.AddRange(sourceData);
|
|
- targetContext.SaveChanges();
|
|
|
|
|
|
+ await targetContext.SaveChangesAsync();
|
|
|
|
+
|
|
|
|
+ EncryptFile(targetPath, targetConnectionString);
|
|
}
|
|
}
|
|
|
|
|
|
- public static void ImportTable<T>(string sourceConnectionString) where T : class
|
|
|
|
|
|
+ public static async void ImportTable<T>(string sourceConnectionString) where T : class
|
|
{
|
|
{
|
|
|
|
+ CreateExportFolder();
|
|
|
|
+
|
|
|
|
+ var sourcePath = $"{DataBasePath}\\UniformMaterialManagementSystem.db";
|
|
|
|
+ DecryptFile(sourceConnectionString, sourcePath);
|
|
|
|
+
|
|
var optionsBuilderSource = new DbContextOptionsBuilder<SqliteContext>();
|
|
var optionsBuilderSource = new DbContextOptionsBuilder<SqliteContext>();
|
|
- optionsBuilderSource.UseSqlite(sourceConnectionString);
|
|
|
|
|
|
+ optionsBuilderSource.UseSqlite($"Data Source={sourcePath}");
|
|
|
|
|
|
var optionsBuilderTarget = new DbContextOptionsBuilder<SqliteContext>();
|
|
var optionsBuilderTarget = new DbContextOptionsBuilder<SqliteContext>();
|
|
optionsBuilderTarget.UseSqlite("Data Source=UniformMaterialManagementSystem.db");
|
|
optionsBuilderTarget.UseSqlite("Data Source=UniformMaterialManagementSystem.db");
|
|
|
|
|
|
- using var sourceContext = new SqliteContext(optionsBuilderSource.Options);
|
|
|
|
- using var targetContext = new SqliteContext(optionsBuilderTarget.Options);
|
|
|
|
|
|
+ await using var sourceContext = new SqliteContext(optionsBuilderSource.Options);
|
|
|
|
+ await using var targetContext = new SqliteContext(optionsBuilderTarget.Options);
|
|
|
|
|
|
// 确保目标数据库创建
|
|
// 确保目标数据库创建
|
|
- targetContext.Database.EnsureCreated();
|
|
|
|
|
|
+ await targetContext.Database.MigrateAsync();
|
|
|
|
|
|
// 读取源数据
|
|
// 读取源数据
|
|
- var sourceData = sourceContext.Set<T>().ToList();
|
|
|
|
|
|
+ var sourceData = sourceContext.Set<T>()
|
|
|
|
+ .IncludeAll()
|
|
|
|
+ .ToList();
|
|
|
|
|
|
// 获取目标 DbSet
|
|
// 获取目标 DbSet
|
|
var targetDbSet = targetContext.Set<T>();
|
|
var targetDbSet = targetContext.Set<T>();
|
|
@@ -57,7 +80,124 @@ namespace UniformMaterialManagementSystem.Utils
|
|
|
|
|
|
// 添加到目标数据库
|
|
// 添加到目标数据库
|
|
targetDbSet.AddRange(sourceData);
|
|
targetDbSet.AddRange(sourceData);
|
|
- targetContext.SaveChanges();
|
|
|
|
|
|
+ await targetContext.SaveChangesAsync();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private static void CreateExportFolder()
|
|
|
|
+ {
|
|
|
|
+ if (!Directory.Exists(DataBasePath))
|
|
|
|
+ {
|
|
|
|
+ Directory.CreateDirectory(DataBasePath);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public static IQueryable<TEntity> IncludeAll<TEntity>(this DbSet<TEntity> dbSet, int maxDepth = int.MaxValue) where TEntity :class
|
|
|
|
+ {
|
|
|
|
+ IQueryable<TEntity> result = dbSet;
|
|
|
|
+ var context = dbSet.GetService<ICurrentDbContext>().Context;
|
|
|
|
+ var includePaths = GetIncludePaths<TEntity>(context, maxDepth);
|
|
|
|
+
|
|
|
|
+ foreach (var includePath in includePaths)
|
|
|
|
+ {
|
|
|
|
+ result = result.Include(includePath);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return result;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private static IEnumerable<string> GetIncludePaths<T>(DbContext context, int maxDepth = int.MaxValue)
|
|
|
|
+ {
|
|
|
|
+ if (maxDepth < 0)
|
|
|
|
+ throw new ArgumentOutOfRangeException(nameof(maxDepth));
|
|
|
|
+
|
|
|
|
+ var entityType = context.Model.FindEntityType(typeof(T));
|
|
|
|
+ var includedNavigations = new HashSet<INavigation>();
|
|
|
|
+ var stack = new Stack<IEnumerator<INavigation>>();
|
|
|
|
+
|
|
|
|
+ while (true)
|
|
|
|
+ {
|
|
|
|
+ var entityNavigations = new List<INavigation>();
|
|
|
|
+
|
|
|
|
+ if (stack.Count <= maxDepth)
|
|
|
|
+ {
|
|
|
|
+ if (entityType != null)
|
|
|
|
+ foreach (var navigation in entityType.GetNavigations())
|
|
|
|
+ {
|
|
|
|
+ if (includedNavigations.Add(navigation))
|
|
|
|
+ entityNavigations.Add(navigation);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (entityNavigations.Count == 0)
|
|
|
|
+ {
|
|
|
|
+ if (stack.Count > 0)
|
|
|
|
+ yield return string.Join(".", stack.Reverse().Select(e => e.Current.Name));
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ foreach (var navigation in entityNavigations)
|
|
|
|
+ {
|
|
|
|
+ var inverseNavigation = navigation.Inverse;
|
|
|
|
+ if (inverseNavigation != null)
|
|
|
|
+ includedNavigations.Add(inverseNavigation);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ stack.Push(entityNavigations.GetEnumerator());
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ while (stack.Count > 0 && !stack.Peek().MoveNext())
|
|
|
|
+ stack.Pop();
|
|
|
|
+
|
|
|
|
+ if (stack.Count == 0)
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ entityType = stack.Peek().Current.TargetEntityType;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private static void EncryptFile(string inputFile, string outputFile)
|
|
|
|
+ {
|
|
|
|
+ // 生成密钥和初始化向量
|
|
|
|
+ GenerateAesKeyAndIv(out var key, out var iv);
|
|
|
|
+
|
|
|
|
+ using var aesAlg = Aes.Create();
|
|
|
|
+ aesAlg.Key = key;
|
|
|
|
+ aesAlg.IV = iv;
|
|
|
|
+
|
|
|
|
+ var encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
|
|
|
|
+
|
|
|
|
+ using var outFileStream = new FileStream(outputFile, FileMode.Create);
|
|
|
|
+ using var csEncrypt = new CryptoStream(outFileStream, encryptor, CryptoStreamMode.Write);
|
|
|
|
+ using var inFileStream = new FileStream(inputFile, FileMode.Open);
|
|
|
|
+
|
|
|
|
+ inFileStream.CopyTo(csEncrypt);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private static void DecryptFile(string inputFile, string outputFile)
|
|
|
|
+ {
|
|
|
|
+ // 生成密钥和初始化向量
|
|
|
|
+ GenerateAesKeyAndIv(out var key, out var iv);
|
|
|
|
+
|
|
|
|
+ using var aesAlg = Aes.Create();
|
|
|
|
+ aesAlg.Key = key;
|
|
|
|
+ aesAlg.IV = iv;
|
|
|
|
+
|
|
|
|
+ var decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
|
|
|
|
+
|
|
|
|
+ using var fileStream = new FileStream(inputFile, FileMode.Open);
|
|
|
|
+ using var csDecrypt = new CryptoStream(fileStream, decryptor, CryptoStreamMode.Read);
|
|
|
|
+ using var outFileStream = new FileStream(outputFile, FileMode.Create);
|
|
|
|
+
|
|
|
|
+ csDecrypt.CopyTo(outFileStream);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private static void GenerateAesKeyAndIv(out byte[] key, out byte[] iv)
|
|
|
|
+ {
|
|
|
|
+ using var pdb = new Rfc2898DeriveBytes(Password, [0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76
|
|
|
|
+ ]);
|
|
|
|
+
|
|
|
|
+ key = pdb.GetBytes(32); // 256位密钥
|
|
|
|
+ iv = pdb.GetBytes(16); // 128位IV
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|