基于SqlSugar初始化数据库

📅 2026/8/9 2:38:30
基于SqlSugar初始化数据库
增量更新表结构/// summary/// 初始化数据库/// /summary/// param namedb/param/// param nameconfig/paramprivatestaticvoidInitDatabase(SqlSugarScopedb,DbConnectionConfigconfig){SqlSugarScopeProviderdbProviderdb.GetConnectionScope(config.ConfigId);// 兼容金仓dbProvider.CurrentConnectionConfig.MoreSettings.DatabaseModelSqlSugar.DbType.MySql;dbProvider.CurrentConnectionConfig.MoreSettings.IsAutoToUpperfalse;dbProvider.CurrentConnectionConfig.MoreSettings.DisableNvarchartrue;// 初始化/创建数据库if(config.DbSettings.EnableInitDb){Console.WriteLine($初始化数据库{config.DbType}-{config.ConfigId}-{config.ConnectionString});if(config.DbType!SqlSugar.DbType.Oracle)dbProvider.DbMaintenance.CreateDatabase();}// 初始化表结构if(config.TableSettings.EnableInitTable){Console.WriteLine($初始化表结构{config.DbType}-{config.ConfigId});varentityTypesApp.EffectiveTypes.Where(u!u.IsInterface!u.IsAbstractu.IsClassu.IsDefined(typeof(SugarTable),false)).Where(u!u.GetCustomAttributesIgnoreTableAttribute().Any()).WhereIF(config.TableSettings.EnableIncreTable,uu.IsDefined(typeof(IncreTableAttribute),false)).ToList();if(config.ConfigId.ToString()SqlSugarConst.MainConfigId)// 默认库有系统表特性、没有日志表和租户表特性entityTypesentityTypes.Where(uu.GetCustomAttributesSysTableAttribute().Any()||(!u.GetCustomAttributesLogTableAttribute().Any()!u.GetCustomAttributesTenantAttribute().Any())).ToList();elseif(config.ConfigId.ToString()SqlSugarConst.LogConfigId)// 日志库entityTypesentityTypes.Where(uu.GetCustomAttributesLogTableAttribute().Any()).ToList();elseentityTypesentityTypes.Where(uu.GetCustomAttributeTenantAttribute()?.configId.ToString()config.ConfigId.ToString()).ToList();// 自定义的库// 按是否分表分组减少循环内反射开销varsplitTypesnewListType();// 分表: 按时间等把同一张表分成多张表物理级别的varnormalTypesnewListType(entityTypes.Count);// 普通表foreach(vartinentityTypes){if(t.GetCustomAttributeSplitTableAttribute()!null)splitTypes.Add(t);elsenormalTypes.Add(t);}// 预检查获取数据库中现有表名集合忽略大小写vardbTableNamesnewHashSetstring(dbProvider.DbMaintenance.GetTableInfoList(false).Select(tt.Name),StringComparer.OrdinalIgnoreCase);// 获取所有实体信息避免重复反射varentityInfosnormalTypes.Select(tnew{Typet,InfodbProvider.EntityMaintenance.GetEntityInfo(t)}).ToList();// 缓存数据库中已存在表的字段信息表名-字段名集合忽略大小写vardbTableColumnMapnewDictionarystring,HashSetstring(StringComparer.OrdinalIgnoreCase);foreach(variteminentityInfos){vartableNameitem.Info.DbTableName;if(string.IsNullOrEmpty(tableName)||!dbTableNames.Contains(tableName))continue;if(!dbTableColumnMap.ContainsKey(tableName)){dbTableColumnMap[tableName]newHashSetstring(dbProvider.DbMaintenance.GetColumnInfosByTableName(tableName).Select(cc.DbColumnName),StringComparer.OrdinalIgnoreCase);}}// 筛选需要初始化的表表不存在 或 字段缺失varneedTypesentityInfos.Where(item{vartableNameitem.Info.DbTableName;// 表不存在于数据库中 - 需要初始化if(string.IsNullOrEmpty(tableName)||!dbTableNames.Contains(tableName))returntrue;// 字段信息未获取到 - 默认需要初始化if(!dbTableColumnMap.TryGetValue(tableName,outvardbColumns))returntrue;// 存在实体字段不在数据库中 - 需要初始化 (排除导航属性和已忽略列)returnitem.Info.Columns.Any(cc.Navigatnull// 排除导航属性!c.IsIgnore// 排除已忽略的列!string.IsNullOrEmpty(c.DbColumnName)!dbColumns.Contains(c.DbColumnName));}).Select(itemitem.Type).ToList();intcount0,sumneedTypes.Count;foreach(varentityTypeinneedTypes){Console.WriteLine($表变更{entityType}({count}/{sum}));if(entityType.GetCustomAttributeSplitTableAttribute()null)dbProvider.CodeFirst.InitTables(entityType);}// 批量创建 dbProvider.CodeFirst.InitTables(needTypes.ToArray());// 分表仍需逐个创建SqlSugar 分表 API 不支持批量数组count0;sumsplitTypes.Count;foreach(varentityTypeinsplitTypes){Console.WriteLine($分表变更{entityType}({count}/{sum}));dbProvider.CodeFirst.SplitTables().InitTables(entityType);}}// 初始化种子数据if(config.SeedSettings.EnableInitSeed){_isHandlingSeedDatatrue;Console.WriteLine($初始化种子数据{config.DbType}-{config.ConfigId});varseedDataTypesApp.EffectiveTypes.Where(u!u.IsInterface!u.IsAbstractu.IsClassu.GetInterfaces().Any(ii.HasImplementedRawGeneric(typeof(ISqlSugarEntitySeedData)))).WhereIF(config.SeedSettings.EnableIncreSeed,uu.IsDefined(typeof(IncreSeedAttribute),false)).OrderBy(uu.GetCustomAttributes(typeof(SeedDataAttribute),false).Length0?((SeedDataAttribute)u.GetCustomAttributes(typeof(SeedDataAttribute),false)[0]).Order:0).ToList();intcount0,sumseedDataTypes.Count;foreach(varseedTypeinseedDataTypes){varentityTypeseedType.GetInterfaces().First().GetGenericArguments().First();if(config.ConfigId.ToString()SqlSugarConst.MainConfigId)// 默认库有系统表特性、没有日志表和租户表特性{if(entityType.GetCustomAttributeSysTableAttribute()null(entityType.GetCustomAttributeLogTableAttribute()!null||entityType.GetCustomAttributeTenantAttribute()!null))continue;}elseif(config.ConfigId.ToString()SqlSugarConst.LogConfigId)// 日志库{if(entityType.GetCustomAttributeLogTableAttribute()null)continue;}else{varattentityType.GetCustomAttributeTenantAttribute();// 自定义的库if(attnull||att.configId.ToString()!config.ConfigId.ToString())continue;}varinstanceActivator.CreateInstance(seedType);varhasDataMethodseedType.GetMethod(HasData);varseedData((IEnumerable)hasDataMethod?.Invoke(instance,null))?.Castobject();if(seedDatanull)continue;varentityInfodbProvider.EntityMaintenance.GetEntityInfo(entityType);if(entityType.GetCustomAttributeSplitTableAttribute(true)!null){//拆分表的操作需要实体类型而通过反射很难实现//所以这里将Init方法写在“种子数据类”内部再传入 db 反射调用varhasInitMethodseedType.GetMethod(Init);varparametersnewobject[]{db};hasInitMethod?.Invoke(instance,parameters);}else{if(entityInfo.Columns.Any(uu.IsPrimarykey)){// 按主键进行批量增加和更新varstoragedbProvider.StorageableByObject(seedData.ToList()).ToStorage();// 先修改再插入否则会更新修改时间字段if(seedType.GetCustomAttributeIgnoreUpdateSeedAttribute()null)// 有忽略更新种子特性时则不更新{intupdateCountstorage.AsUpdateable.IgnoreColumns(entityInfo.Columns.Where(uu.PropertyInfo.GetCustomAttributeIgnoreUpdateSeedColumnAttribute()!null).Select(uu.PropertyName).ToArray()).ExecuteCommand();Console.WriteLine($ 修改{updateCount}/{seedData.Count()}条记录);}intinsertCountstorage.AsInsertable.ExecuteCommand();if(insertCount0){Console.WriteLine($添加数据{entityInfo.DbTableName}({count}/{sum}种子数据{seedData.Count()}) 插入{insertCount}条记录);}}else{// 无主键则只进行插入if(!dbProvider.Queryable(entityInfo.DbTableName,entityInfo.DbTableName).Any())dbProvider.InsertableByObject(seedData.ToList()).ExecuteCommand();}}}_isHandlingSeedDatafalse;}}