Browse Source

新增应用程序启动、正常退出、异常退出日志
新增 dbconfig.json.syncDataIncludeTables同步数据包含表和syncDataExcludeTables同步数据排除表
同步数据重做,支持中间表数据任意导,不再受主键影响,新增不再修改创建数据,修改无数据变动不再更新修改数据。

zhontai 2 years ago
parent
commit
2ad819709c

+ 4 - 0
src/hosts/ZhonTai.Host/Configs/dbconfig.json

@@ -36,6 +36,10 @@
   "sysUpdateData": false,
   //同步数据地址
   //"SyncDataPath": "InitData/Admin/Vue2",
+  //同步数据包含表
+  "syncDataIncludeTables": [],
+  //同步数据排除表
+  "syncDataExcludeTables": [],
 
   //项目初始化不开启生成数据,发布生产环境前,如果开发环境有配置数据需要更新数据包,可以开启生成数据包,使用完记得关闭
   //开启生成数据前先关闭createDb syncStructure syncData sysUpdateData

+ 2 - 2
src/hosts/ZhonTai.Host/Configs/ossconfig.json

@@ -8,9 +8,9 @@
     "Md5": false,
     //文件最大大小
     "MaxSize": 104857600,
-    //包含文件拓展名
+    //包含文件拓展名列表
     "IncludeExtension": [],
-    //排除文件拓展名
+    //排除文件拓展名列表
     "ExcludeExtension": [ ".exe", ".dll", ".jar" ]
   },
   //文件存储供应商

+ 6 - 2
src/hosts/ZhonTai.Host/nlog.config

@@ -9,7 +9,9 @@
   <targets>
     <!-- 调试  -->
     <target xsi:type="File" name="debug" fileName="../logs/debug-${shortdate}.log" layout="${longdate}|${event-properties:item=EventId_Id}|${uppercase:${level}}|${logger}|${message} ${exception:format=tostring}|url: ${aspnet-request-url}|action: ${aspnet-mvc-action}" />
-    <!-- 警告  -->
+	<!-- 信息  -->
+	<target xsi:type="File" name="info" fileName="../logs/info-${shortdate}.log" layout="${longdate}|${event-properties:item=EventId_Id}|${uppercase:${level}}|${logger}|${message} ${exception:format=tostring}|url: ${aspnet-request-url}|action: ${aspnet-mvc-action}" />
+	<!-- 警告  -->
     <target xsi:type="File" name="warn" fileName="../logs/warn-${shortdate}.log" layout="${longdate}|${event-properties:item=EventId_Id}|${uppercase:${level}}|${logger}|${message} ${exception:format=tostring}|url: ${aspnet-request-url}|action: ${aspnet-mvc-action}" />
     <!-- 错误  -->
     <target xsi:type="File" name="error" fileName="../logs/error-${shortdate}.log" layout="${longdate}|${event-properties:item=EventId_Id}|${uppercase:${level}}|${logger}|${message} ${exception:format=tostring}|url: ${aspnet-request-url}|action: ${aspnet-mvc-action}" />
@@ -43,8 +45,10 @@
     <!-- 调试  -->
     <logger name="*" minlevel="Trace" maxlevel="Debug" writeTo="debug" />
     <logger name="*" minlevel="Trace" writeTo="console" />
+	<!-- 信息  -->
+	<logger name="*" minlevel="Info" maxlevel="Info" writeTo="info" />
     <!-- 警告  -->
-    <logger name="*" minlevel="Info" maxlevel="Warn" writeTo="warn" />
+    <logger name="*" minlevel="Warn" maxlevel="Warn" writeTo="warn" />
     <!-- 错误  -->
     <logger name="*" minlevel="Error" maxlevel="Fatal" writeTo="error" />
   </rules>

+ 10 - 0
src/platform/ZhonTai.Admin/Core/Configs/DbConfig.cs

@@ -68,6 +68,16 @@ public class DbConfig
     /// </summary>
     public string SyncDataPath { get; set; } = "InitData/Admin";
 
+    /// <summary>
+    /// 同步数据包含表列表
+    /// </summary>
+    public string[] SyncDataIncludeTables { get; set; }
+
+    /// <summary>
+    /// 同步数据排除表列表
+    /// </summary>
+    public string[] SyncDataExcludeTables { get; set; }
+
     /// <summary>
     /// 建库
     /// </summary>

+ 2 - 2
src/platform/ZhonTai.Admin/Core/Configs/OSSConfig.cs

@@ -84,12 +84,12 @@ public class LocalUploadConfig
     public long MaxSize { get; set; } = 104857600;
 
     /// <summary>
-    /// 包含文件拓展名
+    /// 包含文件拓展名列表
     /// </summary>
     public string[] IncludeExtension { get; set; }
 
     /// <summary>
-    /// 排除文件拓展名
+    /// 排除文件拓展名列表
     /// </summary>
     public string[] ExcludeExtension { get; set; }
 }

+ 5 - 15
src/platform/ZhonTai.Admin/Core/Db/Data/SyncData.cs

@@ -3,11 +3,9 @@ using System.Linq;
 using System.Threading.Tasks;
 using System.IO;
 using Newtonsoft.Json;
-using FreeSql;
 using FreeSql.DataAnnotations;
 using ZhonTai.Common.Helpers;
 using ZhonTai.Admin.Core.Configs;
-using ZhonTai.Admin.Core.Consts;
 
 namespace ZhonTai.Admin.Core.Db.Data;
 
@@ -39,14 +37,12 @@ public abstract class SyncData
     /// </summary>
     /// <typeparam name="T"></typeparam>
     /// <param name="db"></param>
-    /// <param name="unitOfWork"></param>
     /// <param name="tran"></param>
     /// <param name="dataList"></param>
     /// <param name="dbConfig"></param>
     /// <returns></returns>
     protected virtual async Task InitDataAsync<T>(
         IFreeSql db,
-        IUnitOfWork unitOfWork,
         System.Data.Common.DbTransaction tran,
         T[] dataList,
         DbConfig dbConfig = null
@@ -57,20 +53,14 @@ public abstract class SyncData
 
         try
         {
-            //if (await db.Queryable<T>().DisableGlobalFilter(FilterNames.Tenant, FilterNames.Member).AnyAsync())
-            //{
-            //    Console.WriteLine($" table: {tableName} record already exists");
-            //    return;
-            //}
-
             if (!(dataList?.Length > 0))
             {
-                Console.WriteLine($" table: {tableName} import data []");
+                Console.WriteLine($"table: {tableName} import data []");
                 return;
             }
 
             var insertOrUpdate = db.InsertOrUpdate<T>();
-            if (unitOfWork != null)
+            if (tran != null)
             {
                 insertOrUpdate = insertOrUpdate.WithTransaction(tran);
             }
@@ -80,11 +70,11 @@ public abstract class SyncData
             }
             await insertOrUpdate.SetSource(dataList).ExecuteAffrowsAsync();
 
-            Console.WriteLine($" table: {tableName} sync data succeed");
+            Console.WriteLine($"table: {tableName} sync data succeed");
         }
         catch (Exception ex)
         {
-            Console.WriteLine($" table: {tableName} sync data failed.\n{ex.Message}");
+            Console.WriteLine($"table: {tableName} sync data failed.\n{ex.Message}");
             throw;
         }
     }
@@ -96,7 +86,7 @@ public abstract class SyncData
         var filePath = Path.Combine(AppContext.BaseDirectory, $"{path}/{fileName}").ToPath();
         if (!File.Exists(filePath))
         {
-            var msg = $"文件{filePath}不存在";
+            var msg = $"数据文件{filePath}不存在";
             Console.WriteLine(msg);
             throw new Exception(msg);
         }

+ 42 - 42
src/platform/ZhonTai.Admin/Core/Db/DbHelper.cs

@@ -47,7 +47,7 @@ public class DbHelper
 
         try
         {
-            Console.WriteLine($"{Environment.NewLine} create database started");
+            Console.WriteLine($"{Environment.NewLine}create database started");
             var filePath = Path.Combine(AppContext.BaseDirectory, "Configs/createdbsql.txt").ToPath();
             if (File.Exists(filePath))
             {
@@ -59,11 +59,11 @@ public class DbHelper
             }
 
             await db.Ado.ExecuteNonQueryAsync(dbConfig.CreateDbSql);
-            Console.WriteLine(" create database succeed");
+            Console.WriteLine("create database succeed");
         }
         catch (Exception e)
         {
-            Console.WriteLine($" create database failed.\n {e.Message}");
+            Console.WriteLine($"create database failed.\n {e.Message}");
         }
     }
 
@@ -223,7 +223,7 @@ public class DbHelper
     {
         if (e.Sql.NotNull())
         {
-            Console.WriteLine(" sync structure sql:\n" + e.Sql);
+            Console.WriteLine("sync structure sql:\n" + e.Sql);
         }
     }
 
@@ -234,7 +234,7 @@ public class DbHelper
     {
         //打印结构比对脚本
         //var dDL = db.CodeFirst.GetComparisonDDLStatements<PermissionEntity>();
-        //Console.WriteLine($"{Environment.NewLine} " + dDL);
+        //Console.WriteLine($"{Environment.NewLine}" + dDL);
 
         //打印结构同步脚本
         if(dbConfig.SyncStructureSql)
@@ -244,7 +244,7 @@ public class DbHelper
 
         // 同步结构
         var dbType = dbConfig.Type.ToString();
-        Console.WriteLine($"{Environment.NewLine} {(msg.NotNull() ? msg : $"sync {dbType} structure")} started");
+        Console.WriteLine($"{Environment.NewLine}{(msg.NotNull() ? msg : $"sync {dbType} structure")} started");
 
         if (dbConfig.Type == DataType.Oracle)
         {
@@ -260,7 +260,7 @@ public class DbHelper
             db.Aop.SyncStructureAfter -= SyncStructureAfter;
         }
 
-        Console.WriteLine($" {(msg.NotNull() ? msg : $"sync {dbType} structure")} succeed");
+        Console.WriteLine($"{(msg.NotNull() ? msg : $"sync {dbType} structure")} succeed");
     }
 
     private static void SyncDataCurdBefore(object? s, CurdBeforeEventArgs e)
@@ -357,7 +357,7 @@ public class DbHelper
     {
         try
         {
-            Console.WriteLine($"{Environment.NewLine} sync data started");
+            Console.WriteLine($"{Environment.NewLine}sync data started");
 
             if (dbConfig.AssemblyNames?.Length > 0)
             {
@@ -387,11 +387,11 @@ public class DbHelper
                 db.Aop.AuditValue -= SyncDataAuditValue;
             }
 
-            Console.WriteLine($" sync data succeed{Environment.NewLine}");
+            Console.WriteLine($"sync data succeed{Environment.NewLine}");
         }
         catch (Exception ex)
         {
-            throw new Exception($" sync data failed.\n{ex.Message}");
+            throw new Exception($"sync data failed.\n{ex.Message}");
         }
     }
 
@@ -407,7 +407,7 @@ public class DbHelper
     {
         try
         {
-            Console.WriteLine($"{Environment.NewLine} generate data started");
+            Console.WriteLine($"{Environment.NewLine}generate data started");
 
             if (dbConfig.AssemblyNames?.Length > 0)
             {
@@ -423,11 +423,11 @@ public class DbHelper
                 }
             }
 
-            Console.WriteLine($" generate data succeed{Environment.NewLine}");
+            Console.WriteLine($"generate data succeed{Environment.NewLine}");
         }
         catch (Exception ex)
         {
-            throw new Exception($" generate data failed。\n{ex.Message}{Environment.NewLine}");
+            throw new Exception($"generate data failed。\n{ex.Message}{Environment.NewLine}");
         }
     }
 
@@ -494,6 +494,35 @@ public class DbHelper
                 GenerateDataAsync(fsql, appConfig, dbConfig).Wait();
             }
 
+            #region 初始化数据库
+
+            //同步结构
+            if (dbConfig.SyncStructure)
+            {
+                SyncStructure(fsql, dbConfig: dbConfig, appConfig: appConfig);
+            }
+
+            #region 审计数据
+
+            //计算服务器时间
+            var serverTime = fsql.Ado.QuerySingle(() => DateTime.UtcNow);
+            var timeOffset = DateTime.UtcNow.Subtract(serverTime);
+            TimeOffset = timeOffset;
+            fsql.Aop.AuditValue += (s, e) =>
+            {
+                AuditValue(e, timeOffset, user);
+            };
+
+            #endregion 审计数据
+
+            //同步数据
+            if (dbConfig.SyncData)
+            {
+                SyncDataAsync(fsql, dbConfig, appConfig).Wait();
+            }
+
+            #endregion 初始化数据库
+
             //软删除过滤器
             fsql.GlobalFilter.ApplyOnly<IDelete>(FilterNames.Delete, a => a.IsDeleted == false);
 
@@ -545,35 +574,6 @@ public class DbHelper
 
             hostAppOptions?.ConfigureFreeSql?.Invoke(fsql, dbConfig);
 
-            #region 初始化数据库
-
-            //同步结构
-            if (dbConfig.SyncStructure)
-            {
-                SyncStructure(fsql, dbConfig: dbConfig, appConfig: appConfig);
-            }
-
-            #region 审计数据
-
-            //计算服务器时间
-            var serverTime = fsql.Ado.QuerySingle(() => DateTime.UtcNow);
-            var timeOffset = DateTime.UtcNow.Subtract(serverTime);
-            TimeOffset = timeOffset;
-            fsql.Aop.AuditValue += (s, e) =>
-            {
-                AuditValue(e, timeOffset, user);
-            };
-
-            #endregion 审计数据
-
-            //同步数据
-            if (dbConfig.SyncData)
-            {
-                SyncDataAsync(fsql, dbConfig, appConfig).Wait();
-            }
-
-            #endregion 初始化数据库
-
             #region 监听Curd操作
 
             if (dbConfig.Curd)

+ 77 - 56
src/platform/ZhonTai.Admin/Core/HostApp.cs

@@ -58,6 +58,7 @@ using HealthChecks.UI.Client;
 using Microsoft.AspNetCore.Diagnostics.HealthChecks;
 using Microsoft.Extensions.Caching.Distributed;
 using ZhonTai.Admin.Core.Captcha;
+using NLog;
 
 namespace ZhonTai.Admin.Core;
 
@@ -83,79 +84,99 @@ public class HostApp
     /// <param name="args"></param>
     public void Run(string[] args)
     {
-        var builder = WebApplication.CreateBuilder(args);
+        var logger = LogManager.Setup().LoadConfigurationFromAppSettings().GetCurrentClassLogger();
+        try
+        {
+            //应用程序启动
+            logger.Info("Application startup");
 
-        //使用NLog日志
-        builder.Host.UseNLog();
+            var builder = WebApplication.CreateBuilder(args);
 
-        var services = builder.Services;
-        var env = builder.Environment;
-        var configuration = builder.Configuration;
+            //使用NLog日志
+            builder.Host.UseNLog();
 
-        var configHelper = new ConfigHelper();
-        var appConfig = ConfigHelper.Get<AppConfig>("appconfig", env.EnvironmentName) ?? new AppConfig();
+            var services = builder.Services;
+            var env = builder.Environment;
+            var configuration = builder.Configuration;
 
-        //添加配置
-        builder.Configuration.AddJsonFile("./Configs/ratelimitconfig.json", optional: true, reloadOnChange: true);
-        if (env.EnvironmentName.NotNull())
-        {
-            builder.Configuration.AddJsonFile($"./Configs/ratelimitconfig.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
-        }
-        builder.Configuration.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true);
-        if (env.EnvironmentName.NotNull())
-        {
-            builder.Configuration.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
-        }
+            var configHelper = new ConfigHelper();
+            var appConfig = ConfigHelper.Get<AppConfig>("appconfig", env.EnvironmentName) ?? new AppConfig();
 
-        var oSSConfigRoot = ConfigHelper.Load("ossconfig", env.EnvironmentName, true);
-        services.Configure<OSSConfig>(oSSConfigRoot);
+            //添加配置
+            builder.Configuration.AddJsonFile("./Configs/ratelimitconfig.json", optional: true, reloadOnChange: true);
+            if (env.EnvironmentName.NotNull())
+            {
+                builder.Configuration.AddJsonFile($"./Configs/ratelimitconfig.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
+            }
+            builder.Configuration.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true);
+            if (env.EnvironmentName.NotNull())
+            {
+                builder.Configuration.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
+            }
 
-        //应用配置
-        services.AddSingleton(appConfig);
+            var oSSConfigRoot = ConfigHelper.Load("ossconfig", env.EnvironmentName, true);
+            services.Configure<OSSConfig>(oSSConfigRoot);
 
-        var hostAppContext = new HostAppContext()
-        {
-            Services = services,
-            Environment = env,
-            Configuration = configuration
-        };
+            //应用配置
+            services.AddSingleton(appConfig);
 
-        //使用Autofac容器
-        builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory());
-        //配置Autofac容器
-        builder.Host.ConfigureContainer<ContainerBuilder>(builder =>
-        {
-            // 控制器注入
-            builder.RegisterModule(new ControllerModule());
+            var hostAppContext = new HostAppContext()
+            {
+                Services = services,
+                Environment = env,
+                Configuration = configuration
+            };
 
-            // 单例注入
-            builder.RegisterModule(new SingleInstanceModule(appConfig));
+            //使用Autofac容器
+            builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory());
+            //配置Autofac容器
+            builder.Host.ConfigureContainer<ContainerBuilder>(builder =>
+            {
+                // 控制器注入
+                builder.RegisterModule(new ControllerModule());
 
-            // 模块注入
-            builder.RegisterModule(new RegisterModule(appConfig));
+                // 单例注入
+                builder.RegisterModule(new SingleInstanceModule(appConfig));
 
-            _hostAppOptions?.ConfigureAutofacContainer?.Invoke(builder, hostAppContext);
-        });
+                // 模块注入
+                builder.RegisterModule(new RegisterModule(appConfig));
 
-        //配置Kestrel服务器
-        builder.WebHost.ConfigureKestrel((context, options) =>
-        {
-            //设置应用服务器Kestrel请求体最大为100MB
-            options.Limits.MaxRequestBodySize = appConfig.MaxRequestBodySize;
-        });
+                _hostAppOptions?.ConfigureAutofacContainer?.Invoke(builder, hostAppContext);
+            });
+
+            //配置Kestrel服务器
+            builder.WebHost.ConfigureKestrel((context, options) =>
+            {
+                //设置应用服务器Kestrel请求体最大为100MB
+                options.Limits.MaxRequestBodySize = appConfig.MaxRequestBodySize;
+            });
 
-        //访问地址
-        builder.WebHost.UseUrls(appConfig.Urls);
+            //访问地址
+            builder.WebHost.UseUrls(appConfig.Urls);
 
-        //配置服务
-        ConfigureServices(services, env, configuration, configHelper, appConfig);
+            //配置服务
+            ConfigureServices(services, env, configuration, configHelper, appConfig);
 
-        var app = builder.Build();
+            var app = builder.Build();
 
-        //配置中间件
-        ConfigureMiddleware(app, env, configuration, appConfig);
+            //配置中间件
+            ConfigureMiddleware(app, env, configuration, appConfig);
 
-        app.Run();
+            app.Run();
+
+            //应用程序停止
+            logger.Info("Application shutdown");
+        }
+        catch (Exception exception)
+        {
+            //应用程序异常
+            logger.Error(exception, "Application stopped because of exception");
+            throw;
+        }
+        finally
+        {
+            LogManager.Shutdown();
+        }
     }
 
     /// <summary>

+ 2 - 2
src/platform/ZhonTai.Admin/Domain/Dict/DictEntity.cs

@@ -8,8 +8,8 @@ namespace ZhonTai.Admin.Domain.Dict;
 /// 数据字典
 /// </summary>
 [Table(Name = "ad_dict", OldName = "ad_dictionary")]
-[Index("idx_{tablename}_01", nameof(DictTypeId) + "," + nameof(Name) + "," + nameof(TenantId), true)]
-public partial class DictEntity : EntityTenant
+[Index("idx_{tablename}_01", nameof(DictTypeId) + "," + nameof(Name), true)]
+public partial class DictEntity : EntityBase
 {
     /// <summary>
     /// 字典类型Id

+ 2 - 2
src/platform/ZhonTai.Admin/Domain/DictType/DictTypeEntity.cs

@@ -7,8 +7,8 @@ namespace ZhonTai.Admin.Domain.DictType;
 /// 数据字典类型
 /// </summary>
 [Table(Name = "ad_dict_type", OldName = "ad_dictionary_type")]
-[Index("idx_{tablename}_01", nameof(Name) + "," + nameof(TenantId), true)]
-public class DictTypeEntity : EntityTenant
+[Index("idx_{tablename}_01", nameof(Name), true)]
+public class DictTypeEntity : EntityBase
 {
     /// <summary>
     /// 名称

+ 891 - 34
src/platform/ZhonTai.Admin/Repositories/CustomSyncData.cs

@@ -18,62 +18,919 @@ using ZhonTai.Admin.Core.Db.Data;
 using ZhonTai.Admin.Domain.UserOrg;
 using System.Linq;
 using ZhonTai.Common.Extensions;
+using FreeSql.DataAnnotations;
+using System;
+using FreeSql;
 
 namespace ZhonTai.Admin.Repositories;
 
 public class CustomSyncData : SyncData, ISyncData
 {
+    /// <summary>
+    /// 获得表名
+    /// </summary>
+    /// <typeparam name="T"></typeparam>
+    /// <returns></returns>
+    private static string GetTableName<T>() where T : class, new()
+    {
+        var table = typeof(T).GetCustomAttributes(typeof(TableAttribute), false).FirstOrDefault() as TableAttribute;
+        return table.Name;
+    }
+
+    private static bool IsSyncData(string tableName, DbConfig dbConfig)
+    {
+        var isSyncData = true;
+
+        var hasDataIncludeTables = dbConfig.SyncDataIncludeTables?.Length > 0;
+        if (hasDataIncludeTables && !dbConfig.SyncDataIncludeTables.Contains(tableName))
+        {
+            isSyncData = false;
+        }
+
+        var hasSyncDataExcludeTables = dbConfig.SyncDataExcludeTables?.Length > 0;
+        if (hasSyncDataExcludeTables && dbConfig.SyncDataExcludeTables.Contains(tableName))
+        {
+            isSyncData = false;
+        }
+
+        return isSyncData;
+    }
+
+    /// <summary>
+    /// 初始化字典类型
+    /// </summary>
+    /// <param name="db"></param>
+    /// <param name="unitOfWork"></param>
+    /// <param name="dbConfig"></param>
+    /// <returns></returns>
+    private async Task InitDictTypeAsync(IFreeSql db, IRepositoryUnitOfWork unitOfWork, DbConfig dbConfig)
+    {
+        var tableName = GetTableName<DictTypeEntity>();
+        try
+        {
+            if (!IsSyncData(tableName, dbConfig))
+            {
+                return;
+            }
+
+            var rep = db.GetRepository<DictTypeEntity>();
+            rep.UnitOfWork = unitOfWork;
+
+            //数据列表
+            var dataList = GetData<DictTypeEntity>(path: dbConfig.SyncDataPath);
+
+            if (!(dataList?.Length > 0))
+            {
+                Console.WriteLine($"table: {tableName} import data []");
+                return;
+            }
+
+            //查询
+            var ids = dataList.Select(e => e.Id).ToList();
+            var recordList = await rep.Where(a => ids.Contains(a.Id)).ToListAsync();
+
+            //新增
+            var recordIds = recordList.Select(a => a.Id).ToList();
+            var insertDataList = dataList.Where(a => !recordIds.Contains(a.Id));
+            if (insertDataList.Any())
+            {
+                await rep.InsertAsync(insertDataList);
+            }
+
+            //修改
+            if (recordList?.Count > 0)
+            {
+                var updateDataList = dataList.Where(a => recordIds.Contains(a.Id));
+                await rep.UpdateAsync(updateDataList);
+            }
+
+            Console.WriteLine($"table: {tableName} sync data succeed");
+        }
+        catch (Exception ex)
+        {
+            Console.WriteLine($"table: {tableName} sync data failed.\n{ex.Message}");
+            throw;
+        }
+    }
+
+    /// <summary>
+    /// 初始化字典
+    /// </summary>
+    /// <param name="db"></param>
+    /// <param name="unitOfWork"></param>
+    /// <param name="dbConfig"></param>
+    /// <returns></returns>
+    private async Task InitDictAsync(IFreeSql db, IRepositoryUnitOfWork unitOfWork, DbConfig dbConfig)
+    {
+        var tableName = GetTableName<DictEntity>();
+        try
+        {
+            if (!IsSyncData(tableName, dbConfig))
+            {
+                return;
+            }
+
+            var rep = db.GetRepository<DictEntity>();
+            rep.UnitOfWork = unitOfWork;
+
+            //数据列表
+            var dataList = GetData<DictEntity>(path: dbConfig.SyncDataPath);
+
+            if (!(dataList?.Length > 0))
+            {
+                Console.WriteLine($"table: {tableName} import data []");
+                return;
+            }
+
+            //查询
+            var ids = dataList.Select(e => e.Id).ToList();
+            var recordList = await rep.Where(a => ids.Contains(a.Id)).ToListAsync();
+
+            //新增
+            var recordIds = recordList.Select(a => a.Id).ToList();
+            var insertDataList = dataList.Where(a => !recordIds.Contains(a.Id));
+            if (insertDataList.Any())
+            {
+                await rep.InsertAsync(insertDataList);
+            }
+
+            //修改
+            if (recordList?.Count > 0)
+            {
+                var updateDataList = dataList.Where(a => recordIds.Contains(a.Id));
+                await rep.UpdateAsync(updateDataList);
+            }
+            Console.WriteLine($"table: {tableName} sync data succeed");
+        }
+        catch (Exception ex)
+        {
+            Console.WriteLine($"table: {tableName} sync data failed.\n{ex.Message}");
+            throw;
+        }
+    }
+
+    /// <summary>
+    /// 初始化用户
+    /// </summary>
+    /// <param name="db"></param>
+    /// <param name="unitOfWork"></param>
+    /// <param name="dbConfig"></param>
+    /// <param name="isTenant"></param>
+    /// <returns></returns>
+    private async Task InitUserAsync(IFreeSql db, IRepositoryUnitOfWork unitOfWork, DbConfig dbConfig, bool isTenant)
+    {
+        var tableName = GetTableName<UserEntity>();
+        try
+        {
+            if (!IsSyncData(tableName, dbConfig))
+            {
+                return;
+            }
+
+            var rep = db.GetRepository<UserEntity>();
+            rep.UnitOfWork = unitOfWork;
+
+            //数据列表
+            var dataList = GetData<UserEntity>(isTenant, dbConfig.SyncDataPath);
+
+            if (!(dataList?.Length > 0))
+            {
+                Console.WriteLine($"table: {tableName} import data []");
+                return;
+            }
+
+            //查询
+            var ids = dataList.Select(e => e.Id).ToList();
+            var recordList = await rep.Where(a => ids.Contains(a.Id)).ToListAsync();
+
+            //新增
+            var recordIds = recordList.Select(a => a.Id).ToList();
+            var insertDataList = dataList.Where(a => !recordIds.Contains(a.Id));
+            if (insertDataList.Any())
+            {
+                await rep.InsertAsync(insertDataList);
+            }
+
+            //修改
+            if (recordList?.Count > 0)
+            {
+                var updateDataList = dataList.Where(a => recordIds.Contains(a.Id));
+                await rep.UpdateAsync(updateDataList);
+            }
+            Console.WriteLine($"table: {tableName} sync data succeed");
+        }
+        catch (Exception ex)
+        {
+            Console.WriteLine($"table: {tableName} sync data failed.\n{ex.Message}");
+            throw;
+        }
+    }
+
+    /// <summary>
+    /// 初始化用户员工
+    /// </summary>
+    /// <param name="db"></param>
+    /// <param name="unitOfWork"></param>
+    /// <param name="dbConfig"></param>
+    /// <param name="isTenant"></param>
+    /// <returns></returns>
+    private async Task InitUserStaffAsync(IFreeSql db, IRepositoryUnitOfWork unitOfWork, DbConfig dbConfig, bool isTenant)
+    {
+        var tableName = GetTableName<UserStaffEntity>();
+        try
+        {
+            if (!IsSyncData(tableName, dbConfig))
+            {
+                return;
+            }
+
+            var rep = db.GetRepository<UserStaffEntity>();
+            rep.UnitOfWork = unitOfWork;
+
+            //数据列表
+            var dataList = GetData<UserStaffEntity>(isTenant, dbConfig.SyncDataPath);
+
+            if (!(dataList?.Length > 0))
+            {
+                Console.WriteLine($"table: {tableName} import data []");
+                return;
+            }
+
+            //查询
+            var ids = dataList.Select(e => e.Id).ToList();
+            var recordList = await rep.Where(a => ids.Contains(a.Id)).ToListAsync();
+
+            //新增
+            var recordIds = recordList.Select(a => a.Id).ToList();
+            var insertDataList = dataList.Where(a => !recordIds.Contains(a.Id));
+            if (insertDataList.Any())
+            {
+                await rep.InsertAsync(insertDataList);
+            }
+
+            //修改
+            if (recordList?.Count > 0)
+            {
+                var updateDataList = dataList.Where(a => recordIds.Contains(a.Id));
+                await rep.UpdateAsync(updateDataList);
+            }
+            Console.WriteLine($"table: {tableName} sync data succeed");
+        }
+        catch (Exception ex)
+        {
+            Console.WriteLine($"table: {tableName} sync data failed.\n{ex.Message}");
+            throw;
+        }
+    }
+
+    /// <summary>
+    /// 初始化部门
+    /// </summary>
+    /// <param name="db"></param>
+    /// <param name="unitOfWork"></param>
+    /// <param name="dbConfig"></param>
+    /// <param name="isTenant"></param>
+    /// <returns></returns>
+    private async Task InitOrgAsync(IFreeSql db, IRepositoryUnitOfWork unitOfWork, DbConfig dbConfig, bool isTenant)
+    {
+        var tableName = GetTableName<OrgEntity>();
+        try
+        {
+            if (!IsSyncData(tableName, dbConfig))
+            {
+                return;
+            }
+
+            var rep = db.GetRepository<OrgEntity>();
+            rep.UnitOfWork = unitOfWork;
+
+            //数据列表
+            var dataTree = GetData<OrgEntity>(isTenant, dbConfig.SyncDataPath);
+            var dataList = dataTree.ToList().ToPlainList((a) => a.Childs).ToArray();
+
+            if (!(dataList?.Length > 0))
+            {
+                Console.WriteLine($"table: {tableName} import data []");
+                return;
+            }
+
+            //查询
+            var ids = dataList.Select(e => e.Id).ToList();
+            var recordList = await rep.Where(a => ids.Contains(a.Id)).ToListAsync();
+
+            //新增
+            var recordIds = recordList.Select(a => a.Id).ToList();
+            var insertDataList = dataList.Where(a => !recordIds.Contains(a.Id));
+            if (insertDataList.Any())
+            {
+                await rep.InsertAsync(insertDataList);
+            }
+
+            //修改
+            if (recordList?.Count > 0)
+            {
+                var updateDataList = dataList.Where(a => recordIds.Contains(a.Id));
+                await rep.UpdateAsync(updateDataList);
+            }
+            Console.WriteLine($"table: {tableName} sync data succeed");
+        }
+        catch (Exception ex)
+        {
+            Console.WriteLine($"table: {tableName} sync data failed.\n{ex.Message}");
+            throw;
+        }
+    }
+
+    /// <summary>
+    /// 初始化角色
+    /// </summary>
+    /// <param name="db"></param>
+    /// <param name="unitOfWork"></param>
+    /// <param name="dbConfig"></param>
+    /// <param name="isTenant"></param>
+    /// <returns></returns>
+    private async Task InitRoleAsync(IFreeSql db, IRepositoryUnitOfWork unitOfWork, DbConfig dbConfig, bool isTenant)
+    {
+        var tableName = GetTableName<RoleEntity>();
+        try
+        {
+            if (!IsSyncData(tableName, dbConfig))
+            {
+                return;
+            }
+
+            var rep = db.GetRepository<RoleEntity>();
+            rep.UnitOfWork = unitOfWork;
+
+            //数据列表
+            var dataList = GetData<RoleEntity>(isTenant, dbConfig.SyncDataPath);
+
+            if (!(dataList?.Length > 0))
+            {
+                Console.WriteLine($"table: {tableName} import data []");
+                return;
+            }
+
+            //查询
+            var ids = dataList.Select(e => e.Id).ToList();
+            var recordList = await rep.Where(a => ids.Contains(a.Id)).ToListAsync();
+
+            //新增
+            var recordIds = recordList.Select(a => a.Id).ToList();
+            var insertDataList = dataList.Where(a => !recordIds.Contains(a.Id));
+            if (insertDataList.Any())
+            {
+                await rep.InsertAsync(insertDataList);
+            }
+
+            //修改
+            if (recordList?.Count > 0)
+            {
+                var updateDataList = dataList.Where(a => recordIds.Contains(a.Id));
+                await rep.UpdateAsync(updateDataList);
+            }
+            Console.WriteLine($"table: {tableName} sync data succeed");
+        }
+        catch (Exception ex)
+        {
+            Console.WriteLine($"table: {tableName} sync data failed.\n{ex.Message}");
+            throw;
+        }
+    }
+
+    /// <summary>
+    /// 初始化接口
+    /// </summary>
+    /// <param name="db"></param>
+    /// <param name="unitOfWork"></param>
+    /// <param name="dbConfig"></param>
+    /// <returns></returns>
+    private async Task InitApiAsync(IFreeSql db, IRepositoryUnitOfWork unitOfWork, DbConfig dbConfig)
+    {
+        var tableName = GetTableName<ApiEntity>();
+        try
+        {
+            if (!IsSyncData(tableName, dbConfig))
+            {
+                return;
+            }
+
+            var rep = db.GetRepository<ApiEntity>();
+            rep.UnitOfWork = unitOfWork;
+
+            //数据列表
+            var dataTree = GetData<ApiEntity>(path: dbConfig.SyncDataPath);
+            var dataList = dataTree.ToList().ToPlainList((a) => a.Childs).ToArray();
+
+            if (!(dataList?.Length > 0))
+            {
+                Console.WriteLine($"table: {tableName} import data []");
+                return;
+            }
+
+            //查询
+            var ids = dataList.Select(e => e.Id).ToList();
+            var recordList = await rep.Where(a => ids.Contains(a.Id)).ToListAsync();
+
+            //新增
+            var recordIds = recordList.Select(a => a.Id).ToList();
+            var insertDataList = dataList.Where(a => !recordIds.Contains(a.Id));
+            if (insertDataList.Any())
+            {
+                await rep.InsertAsync(insertDataList);
+            }
+
+            //修改
+            if (recordList?.Count > 0)
+            {
+                var updateDataList = dataList.Where(a => recordIds.Contains(a.Id));
+                await rep.UpdateAsync(updateDataList);
+            }
+            Console.WriteLine($"table: {tableName} sync data succeed");
+        }
+        catch (Exception ex)
+        {
+            Console.WriteLine($"table: {tableName} sync data failed.\n{ex.Message}");
+            throw;
+        }
+    }
+
+    /// <summary>
+    /// 初始化视图
+    /// </summary>
+    /// <param name="db"></param>
+    /// <param name="unitOfWork"></param>
+    /// <param name="dbConfig"></param>
+    /// <returns></returns>
+    private async Task InitViewAsync(IFreeSql db, IRepositoryUnitOfWork unitOfWork, DbConfig dbConfig)
+    {
+        var tableName = GetTableName<ViewEntity>();
+        try
+        {
+            if (!IsSyncData(tableName, dbConfig))
+            {
+                return;
+            }
+
+            var rep = db.GetRepository<ViewEntity>();
+            rep.UnitOfWork = unitOfWork;
+
+            //数据列表
+            var dataTree = GetData<ViewEntity>(path: dbConfig.SyncDataPath);
+            var dataList = dataTree.ToList().ToPlainList((a) => a.Childs).ToArray();
+
+            if (!(dataList?.Length > 0))
+            {
+                Console.WriteLine($"table: {tableName} import data []");
+                return;
+            }
+
+            //查询
+            var ids = dataList.Select(e => e.Id).ToList();
+            var recordList = await rep.Where(a => ids.Contains(a.Id)).ToListAsync();
+
+            //新增
+            var recordIds = recordList.Select(a => a.Id).ToList();
+            var insertDataList = dataList.Where(a => !recordIds.Contains(a.Id));
+            if (insertDataList.Any())
+            {
+                await rep.InsertAsync(insertDataList);
+            }
+
+            //修改
+            if (recordList?.Count > 0)
+            {
+                var updateDataList = dataList.Where(a => recordIds.Contains(a.Id));
+                await rep.UpdateAsync(updateDataList);
+            }
+            Console.WriteLine($"table: {tableName} sync data succeed");
+        }
+        catch (Exception ex)
+        {
+            Console.WriteLine($"table: {tableName} sync data failed.\n{ex.Message}");
+            throw;
+        }
+    }
+
+    /// <summary>
+    /// 初始化权限
+    /// </summary>
+    /// <param name="db"></param>
+    /// <param name="unitOfWork"></param>
+    /// <param name="dbConfig"></param>
+    /// <returns></returns>
+    private async Task InitPermissionAsync(IFreeSql db, IRepositoryUnitOfWork unitOfWork, DbConfig dbConfig)
+    {
+        var tableName = GetTableName<PermissionEntity>();
+        try
+        {
+            if (!IsSyncData(tableName, dbConfig))
+            {
+                return;
+            }
+
+            var rep = db.GetRepository<PermissionEntity>();
+            rep.UnitOfWork = unitOfWork;
+
+            //数据列表
+            var dataTree = GetData<PermissionEntity>(path: dbConfig.SyncDataPath);
+            var dataList = dataTree.ToList().ToPlainList((a) => a.Childs).ToArray();
+
+            if (!(dataList?.Length > 0))
+            {
+                Console.WriteLine($"table: {tableName} import data []");
+                return;
+            }
+
+            //查询
+            var ids = dataList.Select(e => e.Id).ToList();
+            var recordList = await rep.Where(a => ids.Contains(a.Id)).ToListAsync();
+
+            //新增
+            var recordIds = recordList.Select(a => a.Id).ToList();
+            var insertDataList = dataList.Where(a => !recordIds.Contains(a.Id));
+            if (insertDataList.Any())
+            {
+                await rep.InsertAsync(insertDataList);
+            }
+
+            //修改
+            if (recordList?.Count > 0)
+            {
+                var updateDataList = dataList.Where(a => recordIds.Contains(a.Id));
+                await rep.UpdateAsync(updateDataList);
+            }
+            Console.WriteLine($"table: {tableName} sync data succeed");
+        }
+        catch (Exception ex)
+        {
+            Console.WriteLine($"table: {tableName} sync data failed.\n{ex.Message}");
+            throw;
+        }
+    }
+
+    /// <summary>
+    /// 初始化权限接口
+    /// </summary>
+    /// <param name="db"></param>
+    /// <param name="unitOfWork"></param>
+    /// <param name="dbConfig"></param>
+    /// <returns></returns>
+    private async Task InitPermissionApiAsync(IFreeSql db, IRepositoryUnitOfWork unitOfWork, DbConfig dbConfig)
+    {
+        var tableName = GetTableName<PermissionApiEntity>();
+        try
+        {
+            if (!IsSyncData(tableName, dbConfig))
+            {
+                return;
+            }
+
+            var rep = db.GetRepository<PermissionApiEntity>();
+            rep.UnitOfWork = unitOfWork;
+
+            //数据列表
+            var dataList = GetData<PermissionApiEntity>(path: dbConfig.SyncDataPath);
+
+            if (!(dataList?.Length > 0))
+            {
+                Console.WriteLine($"table: {tableName} import data []");
+                return;
+            }
+
+            //查询
+            var permissionIds = dataList.Select(a => a.PermissionId).ToList();
+            var apiIds = dataList.Select(a => a.ApiId).ToList();
+            var records = await rep.Where(a => permissionIds.Contains(a.PermissionId) && apiIds.Contains(a.ApiId)).ToListAsync();
+
+            //新增
+            var recordPermissionIds = dataList.Select(a => a.PermissionId).ToList();
+            var recordApiIds = dataList.Select(a => a.ApiId).ToList();
+            var insertDataList = dataList.Where(a => !(recordPermissionIds.Contains(a.PermissionId) && recordApiIds.Contains(a.ApiId)));
+            if (insertDataList.Any())
+            {
+                await rep.InsertAsync(insertDataList);
+            }
+            Console.WriteLine($"table: {tableName} sync data succeed");
+        }
+        catch (Exception ex)
+        {
+            Console.WriteLine($"table: {tableName} sync data failed.\n{ex.Message}");
+            throw;
+        }
+    }
+
+    /// <summary>
+    /// 初始化用户角色
+    /// </summary>
+    /// <param name="db"></param>
+    /// <param name="unitOfWork"></param>
+    /// <param name="dbConfig"></param>
+    /// <returns></returns>
+    private async Task InitUserRoleAsync(IFreeSql db, IRepositoryUnitOfWork unitOfWork, DbConfig dbConfig)
+    {
+        var tableName = GetTableName<UserRoleEntity>();
+        try
+        {
+            if (!IsSyncData(tableName, dbConfig))
+            {
+                return;
+            }
+
+            var rep = db.GetRepository<UserRoleEntity>();
+            rep.UnitOfWork = unitOfWork;
+
+            //数据列表
+            var dataList = GetData<UserRoleEntity>(path: dbConfig.SyncDataPath);
+
+            if (!(dataList?.Length > 0))
+            {
+                Console.WriteLine($"table: {tableName} import data []");
+                return;
+            }
+
+            //查询
+            var userIds = dataList.Select(a => a.UserId).ToList();
+            var roleIds = dataList.Select(a => a.RoleId).ToList();
+            var records = await rep.Where(a => userIds.Contains(a.UserId) && roleIds.Contains(a.RoleId)).ToListAsync();
+
+            //新增
+            var recordUserIds = dataList.Select(a => a.UserId).ToList();
+            var recordRoleIds = dataList.Select(a => a.RoleId).ToList();
+            var insertDataList = dataList.Where(a => !(recordUserIds.Contains(a.UserId) && recordRoleIds.Contains(a.RoleId)));
+            if (insertDataList.Any())
+            {
+                await rep.InsertAsync(insertDataList);
+            }
+            Console.WriteLine($"table: {tableName} sync data succeed");
+        }
+        catch (Exception ex)
+        {
+            Console.WriteLine($"table: {tableName} sync data failed.\n{ex.Message}");
+            throw;
+        }
+    }
+
+    /// <summary>
+    /// 初始化用户部门
+    /// </summary>
+    /// <param name="db"></param>
+    /// <param name="unitOfWork"></param>
+    /// <param name="dbConfig"></param>
+    /// <returns></returns>
+    private async Task InitUserOrgAsync(IFreeSql db, IRepositoryUnitOfWork unitOfWork, DbConfig dbConfig)
+    {
+        var tableName = GetTableName<UserOrgEntity>();
+        try
+        {
+            if (!IsSyncData(tableName, dbConfig))
+            {
+                return;
+            }
+
+            var rep = db.GetRepository<UserOrgEntity>();
+            rep.UnitOfWork = unitOfWork;
+
+            //数据列表
+            var dataList = GetData<UserOrgEntity>(path: dbConfig.SyncDataPath);
+
+            if (!(dataList?.Length > 0))
+            {
+                Console.WriteLine($"table: {tableName} import data []");
+                return;
+            }
+
+            //查询
+            var userIds = dataList.Select(a => a.UserId).ToList();
+            var orgIds = dataList.Select(a => a.OrgId).ToList();
+            var records = await rep.Where(a => userIds.Contains(a.UserId) && orgIds.Contains(a.OrgId)).ToListAsync();
+
+            //新增
+            var recordUserIds = dataList.Select(a => a.UserId).ToList();
+            var recordOrgIds = dataList.Select(a => a.OrgId).ToList();
+            var insertDataList = dataList.Where(a => !(recordUserIds.Contains(a.UserId) && recordOrgIds.Contains(a.OrgId)));
+            if (insertDataList.Any())
+            {
+                await rep.InsertAsync(insertDataList);
+            }
+            Console.WriteLine($"table: {tableName} sync data succeed");
+        }
+        catch (Exception ex)
+        {
+            Console.WriteLine($"table: {tableName} sync data failed.\n{ex.Message}");
+            throw;
+        }
+    }
+
+    /// <summary>
+    /// 初始化角色权限
+    /// </summary>
+    /// <param name="db"></param>
+    /// <param name="unitOfWork"></param>
+    /// <param name="dbConfig"></param>
+    /// <returns></returns>
+    private async Task InitRolePermissionAsync(IFreeSql db, IRepositoryUnitOfWork unitOfWork, DbConfig dbConfig)
+    {
+        var tableName = GetTableName<RolePermissionEntity>();
+        try
+        {
+            if (!IsSyncData(tableName, dbConfig))
+            {
+                return;
+            }
+
+            var rep = db.GetRepository<RolePermissionEntity>();
+            rep.UnitOfWork = unitOfWork;
+
+            //数据列表
+            var dataList = GetData<RolePermissionEntity>(path: dbConfig.SyncDataPath);
+
+            if (!(dataList?.Length > 0))
+            {
+                Console.WriteLine($"table: {tableName} import data []");
+                return;
+            }
+
+            //查询
+            var roleIds = dataList.Select(a => a.RoleId).ToList();
+            var permissionIds = dataList.Select(a => a.PermissionId).ToList();
+            var records = await rep.Where(a => roleIds.Contains(a.RoleId) && permissionIds.Contains(a.PermissionId)).ToListAsync();
+
+            //新增
+            var recordRoleIds = dataList.Select(a => a.RoleId).ToList();
+            var recordPermissionIds = dataList.Select(a => a.PermissionId).ToList();
+            var insertDataList = dataList.Where(a => !(recordRoleIds.Contains(a.RoleId) && recordPermissionIds.Contains(a.PermissionId)));
+            if (insertDataList.Any())
+            {
+                await rep.InsertAsync(insertDataList);
+            }
+            Console.WriteLine($"table: {tableName} sync data succeed");
+        }
+        catch (Exception ex)
+        {
+            Console.WriteLine($"table: {tableName} sync data failed.\n{ex.Message}");
+            throw;
+        }
+    }
+
+    /// <summary>
+    /// 初始化租户
+    /// </summary>
+    /// <param name="db"></param>
+    /// <param name="unitOfWork"></param>
+    /// <param name="dbConfig"></param>
+    /// <returns></returns>
+    private async Task InitTenantAsync(IFreeSql db, IRepositoryUnitOfWork unitOfWork, DbConfig dbConfig)
+    {
+        var tableName = GetTableName<TenantEntity>();
+        try
+        {
+            if (!IsSyncData(tableName, dbConfig))
+            {
+                return;
+            }
+
+            var rep = db.GetRepository<TenantEntity>();
+            rep.UnitOfWork = unitOfWork;
+
+            //数据列表
+            var dataList = GetData<TenantEntity>(path: dbConfig.SyncDataPath);
+
+            if (!(dataList?.Length > 0))
+            {
+                Console.WriteLine($"table: {tableName} import data []");
+                return;
+            }
+
+            //查询
+            var ids = dataList.Select(e => e.Id).ToList();
+            var recordList = await rep.Where(a => ids.Contains(a.Id)).ToListAsync();
+
+            //新增
+            var recordIds = recordList.Select(a => a.Id).ToList();
+            var insertDataList = dataList.Where(a => !recordIds.Contains(a.Id));
+            if (insertDataList.Any())
+            {
+                await rep.InsertAsync(insertDataList);
+            }
+
+            //修改
+            if (recordList?.Count > 0)
+            {
+                var updateDataList = dataList.Where(a => recordIds.Contains(a.Id));
+                await rep.UpdateAsync(updateDataList);
+            }
+            Console.WriteLine($"table: {tableName} sync data succeed");
+        }
+        catch (Exception ex)
+        {
+            Console.WriteLine($"table: {tableName} sync data failed.\n{ex.Message}");
+            throw;
+        }
+    }
+
+    /// <summary>
+    /// 初始化租户权限
+    /// </summary>
+    /// <param name="db"></param>
+    /// <param name="unitOfWork"></param>
+    /// <param name="dbConfig"></param>
+    /// <returns></returns>
+    private async Task InitTenantPermissionAsync(IFreeSql db, IRepositoryUnitOfWork unitOfWork, DbConfig dbConfig)
+    {
+        var tableName = GetTableName<TenantPermissionEntity>();
+        try
+        {
+            if (!IsSyncData(tableName, dbConfig))
+            {
+                return;
+            }
+
+            var rep = db.GetRepository<TenantPermissionEntity>();
+            rep.UnitOfWork = unitOfWork;
+
+            //数据列表
+            var dataList = GetData<TenantPermissionEntity>(path: dbConfig.SyncDataPath);
+
+            if (!(dataList?.Length > 0))
+            {
+                Console.WriteLine($"table: {tableName} import data []");
+                return;
+            }
+
+            //查询
+            var tenantIds = dataList.Select(a => a.TenantId).ToList();
+            var permissionIds = dataList.Select(a => a.PermissionId).ToList();
+            var records = await rep.Where(a => tenantIds.Contains(a.TenantId) && permissionIds.Contains(a.PermissionId)).ToListAsync();
+
+            //新增
+            var recordTenantIds = dataList.Select(a => a.TenantId).ToList();
+            var recordPermissionIds = dataList.Select(a => a.PermissionId).ToList();
+            var insertDataList = dataList.Where(a => !(tenantIds.Contains(a.TenantId) && recordPermissionIds.Contains(a.PermissionId)));
+            if (insertDataList.Any())
+            {
+                await rep.InsertAsync(insertDataList);
+            }
+            Console.WriteLine($"table: {tableName} sync data succeed");
+        }
+        catch (Exception ex)
+        {
+            Console.WriteLine($"table: {tableName} sync data failed.\n{ex.Message}");
+            throw;
+        }
+    }
+
+    /// <summary>
+    /// 同步数据
+    /// </summary>
+    /// <param name="db"></param>
+    /// <param name="dbConfig"></param>
+    /// <param name="appConfig"></param>
+    /// <returns></returns>
     public virtual async Task SyncDataAsync(IFreeSql db, DbConfig dbConfig = null, AppConfig appConfig = null)
     {
-        using var uow = db.CreateUnitOfWork();
-        using var tran = uow.GetOrBeginTransaction();
-        var isTenant = appConfig.Tenant;
+        using var unitOfWork = db.CreateUnitOfWork();
+
+        try
+        {
+            var isTenant = appConfig.Tenant;
 
-        var dictionaryTypes = GetData<DictTypeEntity>(path: dbConfig.SyncDataPath);
-        await InitDataAsync(db, uow, tran, dictionaryTypes, dbConfig);
+            await InitDictTypeAsync(db, unitOfWork, dbConfig);
 
-        var dictionaries = GetData<DictEntity>(path: dbConfig.SyncDataPath);
-        await InitDataAsync(db, uow, tran, dictionaries, dbConfig);
+            await InitDictAsync(db, unitOfWork, dbConfig);
 
-        var users = GetData<UserEntity>(isTenant, dbConfig.SyncDataPath);
-        await InitDataAsync(db, uow, tran, users, dbConfig);
+            await InitUserAsync(db, unitOfWork, dbConfig, isTenant);
 
-        var staffs = GetData<UserStaffEntity>(isTenant, dbConfig.SyncDataPath);
-        await InitDataAsync(db, uow, tran, staffs, dbConfig);
+            await InitUserStaffAsync(db, unitOfWork, dbConfig, isTenant);
 
-        var orgTree = GetData<OrgEntity>(isTenant, dbConfig.SyncDataPath);
-        await InitDataAsync(db, uow, tran, orgTree.ToList().ToPlainList((a) => a.Childs).ToArray(), dbConfig);
+            await InitOrgAsync(db, unitOfWork, dbConfig, isTenant);
 
-        var roles = GetData<RoleEntity>(isTenant, dbConfig.SyncDataPath);
-        await InitDataAsync(db, uow, tran, roles, dbConfig);
+            await InitRoleAsync(db, unitOfWork, dbConfig, isTenant);
 
-        var apiTree = GetData<ApiEntity>(path: dbConfig.SyncDataPath);
-        await InitDataAsync(db, uow, tran, apiTree.ToList().ToPlainList((a) => a.Childs).ToArray(), dbConfig);
+            await InitApiAsync(db, unitOfWork, dbConfig);
 
-        var viewTree = GetData<ViewEntity>(path: dbConfig.SyncDataPath);
-        await InitDataAsync(db, uow, tran, viewTree.ToList().ToPlainList((a) => a.Childs).ToArray(), dbConfig);
+            await InitViewAsync(db, unitOfWork, dbConfig);
 
-        var permissionTree = GetData<PermissionEntity>(path: dbConfig.SyncDataPath);
-        await InitDataAsync(db, uow, tran, permissionTree.ToList().ToPlainList((a) => a.Childs).ToArray(), dbConfig);
+            await InitPermissionAsync(db, unitOfWork, dbConfig);
 
-        var userRoles = GetData<UserRoleEntity>(path: dbConfig.SyncDataPath);
-        await InitDataAsync(db, uow, tran, userRoles, dbConfig);
+            await InitPermissionApiAsync(db, unitOfWork, dbConfig);
 
-        var userOrgs = GetData<UserOrgEntity>(path: dbConfig.SyncDataPath);
-        await InitDataAsync(db, uow, tran, userOrgs, dbConfig);
+            await InitUserRoleAsync(db, unitOfWork, dbConfig);
 
-        var rolePermissions = GetData<RolePermissionEntity>(path: dbConfig.SyncDataPath);
-        await InitDataAsync(db, uow, tran, rolePermissions, dbConfig);
+            await InitUserOrgAsync(db, unitOfWork, dbConfig);
 
-        var tenants = GetData<TenantEntity>(path: dbConfig.SyncDataPath);
-        await InitDataAsync(db, uow, tran, tenants, dbConfig);
+            await InitRolePermissionAsync(db, unitOfWork, dbConfig);
 
-        var tenantPermissions = GetData<TenantPermissionEntity>(path: dbConfig.SyncDataPath);
-        await InitDataAsync(db, uow, tran, tenantPermissions, dbConfig);
+            await InitTenantAsync(db, unitOfWork, dbConfig);
 
-        var permissionApis = GetData<PermissionApiEntity>(path: dbConfig.SyncDataPath);
-        await InitDataAsync(db, uow, tran, permissionApis, dbConfig);
+            await InitTenantPermissionAsync(db, unitOfWork, dbConfig);
 
-        uow.Commit();
+            unitOfWork.Commit();
+        }
+        catch (Exception)
+        {
+            unitOfWork.Rollback();
+            throw;
+        }
     }
 }

+ 1 - 1
src/platform/ZhonTai.Admin/ZhonTai.Admin.csproj

@@ -26,7 +26,7 @@
 		<PackageReference Include="Lazy.SlideCaptcha.Core" Version="2.0.0" />
 		<PackageReference Include="Mapster" Version="7.3.0" />
 		<PackageReference Include="Microsoft.Extensions.DependencyModel" Version="7.0.0" />
-		<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="7.0.4" />
+		<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="7.0.5" />
 		<PackageReference Include="MiniProfiler.AspNetCore.Mvc" Version="4.2.22" />
 		<PackageReference Include="NLog" Version="5.1.3" />
 		<PackageReference Include="NLog.Web.AspNetCore" Version="5.2.3" />

+ 168 - 4
src/platform/ZhonTai.Admin/ZhonTai.Admin.xml

@@ -665,6 +665,16 @@
             同步数据地址
             </summary>
         </member>
+        <member name="P:ZhonTai.Admin.Core.Configs.DbConfig.SyncDataIncludeTables">
+            <summary>
+            同步数据包含表列表
+            </summary>
+        </member>
+        <member name="P:ZhonTai.Admin.Core.Configs.DbConfig.SyncDataExcludeTables">
+            <summary>
+            同步数据排除表列表
+            </summary>
+        </member>
         <member name="P:ZhonTai.Admin.Core.Configs.DbConfig.CreateDb">
             <summary>
             建库
@@ -842,12 +852,12 @@
         </member>
         <member name="P:ZhonTai.Admin.Core.Configs.LocalUploadConfig.IncludeExtension">
             <summary>
-            包含文件拓展名
+            包含文件拓展名列表
             </summary>
         </member>
         <member name="P:ZhonTai.Admin.Core.Configs.LocalUploadConfig.ExcludeExtension">
             <summary>
-            排除文件拓展名
+            排除文件拓展名列表
             </summary>
         </member>
         <member name="T:ZhonTai.Admin.Core.Configs.OSSConfig">
@@ -1047,13 +1057,12 @@
             <typeparam name="T"></typeparam>
             <returns></returns>
         </member>
-        <member name="M:ZhonTai.Admin.Core.Db.Data.SyncData.InitDataAsync``1(IFreeSql,FreeSql.IUnitOfWork,System.Data.Common.DbTransaction,``0[],ZhonTai.Admin.Core.Configs.DbConfig)">
+        <member name="M:ZhonTai.Admin.Core.Db.Data.SyncData.InitDataAsync``1(IFreeSql,System.Data.Common.DbTransaction,``0[],ZhonTai.Admin.Core.Configs.DbConfig)">
             <summary>
             初始化数据表数据
             </summary>
             <typeparam name="T"></typeparam>
             <param name="db"></param>
-            <param name="unitOfWork"></param>
             <param name="tran"></param>
             <param name="dataList"></param>
             <param name="dbConfig"></param>
@@ -3573,6 +3582,161 @@
             </summary>
             <typeparam name="TEntity"></typeparam>
         </member>
+        <member name="M:ZhonTai.Admin.Repositories.CustomSyncData.GetTableName``1">
+            <summary>
+            获得表名
+            </summary>
+            <typeparam name="T"></typeparam>
+            <returns></returns>
+        </member>
+        <member name="M:ZhonTai.Admin.Repositories.CustomSyncData.InitDictTypeAsync(IFreeSql,FreeSql.IRepositoryUnitOfWork,ZhonTai.Admin.Core.Configs.DbConfig)">
+            <summary>
+            初始化字典类型
+            </summary>
+            <param name="db"></param>
+            <param name="unitOfWork"></param>
+            <param name="dbConfig"></param>
+            <returns></returns>
+        </member>
+        <member name="M:ZhonTai.Admin.Repositories.CustomSyncData.InitDictAsync(IFreeSql,FreeSql.IRepositoryUnitOfWork,ZhonTai.Admin.Core.Configs.DbConfig)">
+            <summary>
+            初始化字典
+            </summary>
+            <param name="db"></param>
+            <param name="unitOfWork"></param>
+            <param name="dbConfig"></param>
+            <returns></returns>
+        </member>
+        <member name="M:ZhonTai.Admin.Repositories.CustomSyncData.InitUserAsync(IFreeSql,FreeSql.IRepositoryUnitOfWork,ZhonTai.Admin.Core.Configs.DbConfig,System.Boolean)">
+            <summary>
+            初始化用户
+            </summary>
+            <param name="db"></param>
+            <param name="unitOfWork"></param>
+            <param name="dbConfig"></param>
+            <param name="isTenant"></param>
+            <returns></returns>
+        </member>
+        <member name="M:ZhonTai.Admin.Repositories.CustomSyncData.InitUserStaffAsync(IFreeSql,FreeSql.IRepositoryUnitOfWork,ZhonTai.Admin.Core.Configs.DbConfig,System.Boolean)">
+            <summary>
+            初始化用户员工
+            </summary>
+            <param name="db"></param>
+            <param name="unitOfWork"></param>
+            <param name="dbConfig"></param>
+            <param name="isTenant"></param>
+            <returns></returns>
+        </member>
+        <member name="M:ZhonTai.Admin.Repositories.CustomSyncData.InitOrgAsync(IFreeSql,FreeSql.IRepositoryUnitOfWork,ZhonTai.Admin.Core.Configs.DbConfig,System.Boolean)">
+            <summary>
+            初始化部门
+            </summary>
+            <param name="db"></param>
+            <param name="unitOfWork"></param>
+            <param name="dbConfig"></param>
+            <param name="isTenant"></param>
+            <returns></returns>
+        </member>
+        <member name="M:ZhonTai.Admin.Repositories.CustomSyncData.InitRoleAsync(IFreeSql,FreeSql.IRepositoryUnitOfWork,ZhonTai.Admin.Core.Configs.DbConfig,System.Boolean)">
+            <summary>
+            初始化角色
+            </summary>
+            <param name="db"></param>
+            <param name="unitOfWork"></param>
+            <param name="dbConfig"></param>
+            <param name="isTenant"></param>
+            <returns></returns>
+        </member>
+        <member name="M:ZhonTai.Admin.Repositories.CustomSyncData.InitApiAsync(IFreeSql,FreeSql.IRepositoryUnitOfWork,ZhonTai.Admin.Core.Configs.DbConfig)">
+            <summary>
+            初始化接口
+            </summary>
+            <param name="db"></param>
+            <param name="unitOfWork"></param>
+            <param name="dbConfig"></param>
+            <returns></returns>
+        </member>
+        <member name="M:ZhonTai.Admin.Repositories.CustomSyncData.InitViewAsync(IFreeSql,FreeSql.IRepositoryUnitOfWork,ZhonTai.Admin.Core.Configs.DbConfig)">
+            <summary>
+            初始化视图
+            </summary>
+            <param name="db"></param>
+            <param name="unitOfWork"></param>
+            <param name="dbConfig"></param>
+            <returns></returns>
+        </member>
+        <member name="M:ZhonTai.Admin.Repositories.CustomSyncData.InitPermissionAsync(IFreeSql,FreeSql.IRepositoryUnitOfWork,ZhonTai.Admin.Core.Configs.DbConfig)">
+            <summary>
+            初始化权限
+            </summary>
+            <param name="db"></param>
+            <param name="unitOfWork"></param>
+            <param name="dbConfig"></param>
+            <returns></returns>
+        </member>
+        <member name="M:ZhonTai.Admin.Repositories.CustomSyncData.InitPermissionApiAsync(IFreeSql,FreeSql.IRepositoryUnitOfWork,ZhonTai.Admin.Core.Configs.DbConfig)">
+            <summary>
+            初始化权限接口
+            </summary>
+            <param name="db"></param>
+            <param name="unitOfWork"></param>
+            <param name="dbConfig"></param>
+            <returns></returns>
+        </member>
+        <member name="M:ZhonTai.Admin.Repositories.CustomSyncData.InitUserRoleAsync(IFreeSql,FreeSql.IRepositoryUnitOfWork,ZhonTai.Admin.Core.Configs.DbConfig)">
+            <summary>
+            初始化用户角色
+            </summary>
+            <param name="db"></param>
+            <param name="unitOfWork"></param>
+            <param name="dbConfig"></param>
+            <returns></returns>
+        </member>
+        <member name="M:ZhonTai.Admin.Repositories.CustomSyncData.InitUserOrgAsync(IFreeSql,FreeSql.IRepositoryUnitOfWork,ZhonTai.Admin.Core.Configs.DbConfig)">
+            <summary>
+            初始化用户部门
+            </summary>
+            <param name="db"></param>
+            <param name="unitOfWork"></param>
+            <param name="dbConfig"></param>
+            <returns></returns>
+        </member>
+        <member name="M:ZhonTai.Admin.Repositories.CustomSyncData.InitRolePermissionAsync(IFreeSql,FreeSql.IRepositoryUnitOfWork,ZhonTai.Admin.Core.Configs.DbConfig)">
+            <summary>
+            初始化角色权限
+            </summary>
+            <param name="db"></param>
+            <param name="unitOfWork"></param>
+            <param name="dbConfig"></param>
+            <returns></returns>
+        </member>
+        <member name="M:ZhonTai.Admin.Repositories.CustomSyncData.InitTenantAsync(IFreeSql,FreeSql.IRepositoryUnitOfWork,ZhonTai.Admin.Core.Configs.DbConfig)">
+            <summary>
+            初始化租户
+            </summary>
+            <param name="db"></param>
+            <param name="unitOfWork"></param>
+            <param name="dbConfig"></param>
+            <returns></returns>
+        </member>
+        <member name="M:ZhonTai.Admin.Repositories.CustomSyncData.InitTenantPermissionAsync(IFreeSql,FreeSql.IRepositoryUnitOfWork,ZhonTai.Admin.Core.Configs.DbConfig)">
+            <summary>
+            初始化租户权限
+            </summary>
+            <param name="db"></param>
+            <param name="unitOfWork"></param>
+            <param name="dbConfig"></param>
+            <returns></returns>
+        </member>
+        <member name="M:ZhonTai.Admin.Repositories.CustomSyncData.SyncDataAsync(IFreeSql,ZhonTai.Admin.Core.Configs.DbConfig,ZhonTai.Admin.Core.Configs.AppConfig)">
+            <summary>
+            同步数据
+            </summary>
+            <param name="db"></param>
+            <param name="dbConfig"></param>
+            <param name="appConfig"></param>
+            <returns></returns>
+        </member>
         <member name="M:ZhonTai.Admin.Repositories.OrgRepository.GetChildIdListAsync(System.Int64)">
             <summary>
             获得本部门和下级部门Id

+ 2 - 2
src/tests/ZhonTai.Tests/ZhonTai.Tests.csproj

@@ -6,8 +6,8 @@
 	</PropertyGroup>
 
   <ItemGroup>
-    <PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="7.0.3" />
-    <PackageReference Include="Microsoft.AspNetCore.TestHost" Version="7.0.3" />
+    <PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="7.0.5" />
+    <PackageReference Include="Microsoft.AspNetCore.TestHost" Version="7.0.5" />
     <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.5.0" />
     <PackageReference Include="xunit" Version="2.4.2" />
     <PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">