三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

基于SqlSugar初始化数据库

基于SqlSugar初始化数据库

增量更新表结构

/// <summary>/// 初始化数据库/// </summary>/// <param name="db"></param>/// <param name="config"></param>privatestaticvoidInitDatabase(SqlSugarScopedb,DbConnectionConfigconfig){SqlSugarScopeProviderdbProvider=db.GetConnectionScope(config.ConfigId);// 兼容金仓dbProvider.CurrentConnectionConfig.MoreSettings.DatabaseModel=SqlSugar.DbType.MySql;dbProvider.CurrentConnectionConfig.MoreSettings.IsAutoToUpper=false;dbProvider.CurrentConnectionConfig.MoreSettings.DisableNvarchar=true;// 初始化/创建数据库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}");varentityTypes=App.EffectiveTypes.Where(u=>!u.IsInterface&&!u.IsAbstract&&u.IsClass&&u.IsDefined(typeof(SugarTable),false)).Where(u=>!u.GetCustomAttributes<IgnoreTableAttribute>().Any()).WhereIF(config.TableSettings.EnableIncreTable,u=>u.IsDefined(typeof(IncreTableAttribute),false)).ToList();if(config.ConfigId.ToString()==SqlSugarConst.MainConfigId)// 默认库(有系统表特性、没有日志表和租户表特性)entityTypes=entityTypes.Where(u=>u.GetCustomAttributes<SysTableAttribute>().Any()||(!u.GetCustomAttributes<LogTableAttribute>().Any()&&!u.GetCustomAttributes<TenantAttribute>().Any())).ToList();elseif(config.ConfigId.ToString()==SqlSugarConst.LogConfigId)// 日志库entityTypes=entityTypes.Where(u=>u.GetCustomAttributes<LogTableAttribute>().Any()).ToList();elseentityTypes=entityTypes.Where(u=>u.GetCustomAttribute<TenantAttribute>()?.configId.ToString()==config.ConfigId.ToString()).ToList();// 自定义的库// 按是否分表分组,减少循环内反射开销varsplitTypes=newList<Type>();// 分表: 按时间等把同一张表分成多张表,物理级别的varnormalTypes=newList<Type>(entityTypes.Count);// 普通表foreach(vartinentityTypes){if(t.GetCustomAttribute<SplitTableAttribute>()!=null)splitTypes.Add(t);elsenormalTypes.Add(t);}// 预检查:获取数据库中现有表名集合(忽略大小写)vardbTableNames=newHashSet<string>(dbProvider.DbMaintenance.GetTableInfoList(false).Select(t=>t.Name),StringComparer.OrdinalIgnoreCase);// 获取所有实体信息,避免重复反射varentityInfos=normalTypes.Select(t=>new{Type=t,Info=dbProvider.EntityMaintenance.GetEntityInfo(t)}).ToList();// 缓存数据库中已存在表的字段信息(表名->字段名集合,忽略大小写)vardbTableColumnMap=newDictionary<string,HashSet<string>>(StringComparer.OrdinalIgnoreCase);foreach(variteminentityInfos){vartableName=item.Info.DbTableName;if(string.IsNullOrEmpty(tableName)||!dbTableNames.Contains(tableName))continue;if(!dbTableColumnMap.ContainsKey(tableName)){dbTableColumnMap[tableName]=newHashSet<string>(dbProvider.DbMaintenance.GetColumnInfosByTableName(tableName).Select(c=>c.DbColumnName),StringComparer.OrdinalIgnoreCase);}}// 筛选需要初始化的表:表不存在 或 字段缺失varneedTypes=entityInfos.Where(item=>{vartableName=item.Info.DbTableName;// 表不存在于数据库中 -> 需要初始化if(string.IsNullOrEmpty(tableName)||!dbTableNames.Contains(tableName))returntrue;// 字段信息未获取到 -> 默认需要初始化if(!dbTableColumnMap.TryGetValue(tableName,outvardbColumns))returntrue;// 存在实体字段不在数据库中 -> 需要初始化 (排除导航属性和已忽略列)returnitem.Info.Columns.Any(c=>c.Navigat==null&&// 排除导航属性!c.IsIgnore&&// 排除已忽略的列!string.IsNullOrEmpty(c.DbColumnName)&&!dbColumns.Contains(c.DbColumnName));}).Select(item=>item.Type).ToList();intcount=0,sum=needTypes.Count;foreach(varentityTypeinneedTypes){Console.WriteLine($"表变更{entityType}({++count}/{sum})");if(entityType.GetCustomAttribute<SplitTableAttribute>()==null)dbProvider.CodeFirst.InitTables(entityType);}// 批量创建 dbProvider.CodeFirst.InitTables(needTypes.ToArray());// 分表仍需逐个创建(SqlSugar 分表 API 不支持批量数组)count=0;sum=splitTypes.Count;foreach(varentityTypeinsplitTypes){Console.WriteLine($"分表变更{entityType}({++count}/{sum})");dbProvider.CodeFirst.SplitTables().InitTables(entityType);}}// 初始化种子数据if(config.SeedSettings.EnableInitSeed){_isHandlingSeedData=true;Console.WriteLine($"初始化种子数据{config.DbType}-{config.ConfigId}");varseedDataTypes=App.EffectiveTypes.Where(u=>!u.IsInterface&&!u.IsAbstract&&u.IsClass&&u.GetInterfaces().Any(i=>i.HasImplementedRawGeneric(typeof(ISqlSugarEntitySeedData<>)))).WhereIF(config.SeedSettings.EnableIncreSeed,u=>u.IsDefined(typeof(IncreSeedAttribute),false)).OrderBy(u=>u.GetCustomAttributes(typeof(SeedDataAttribute),false).Length>0?((SeedDataAttribute)u.GetCustomAttributes(typeof(SeedDataAttribute),false)[0]).Order:0).ToList();intcount=0,sum=seedDataTypes.Count;foreach(varseedTypeinseedDataTypes){varentityType=seedType.GetInterfaces().First().GetGenericArguments().First();if(config.ConfigId.ToString()==SqlSugarConst.MainConfigId)// 默认库(有系统表特性、没有日志表和租户表特性){if(entityType.GetCustomAttribute<SysTableAttribute>()==null&&(entityType.GetCustomAttribute<LogTableAttribute>()!=null||entityType.GetCustomAttribute<TenantAttribute>()!=null))continue;}elseif(config.ConfigId.ToString()==SqlSugarConst.LogConfigId)// 日志库{if(entityType.GetCustomAttribute<LogTableAttribute>()==null)continue;}else{varatt=entityType.GetCustomAttribute<TenantAttribute>();// 自定义的库if(att==null||att.configId.ToString()!=config.ConfigId.ToString())continue;}varinstance=Activator.CreateInstance(seedType);varhasDataMethod=seedType.GetMethod("HasData");varseedData=((IEnumerable)hasDataMethod?.Invoke(instance,null))?.Cast<object>();if(seedData==null)continue;varentityInfo=dbProvider.EntityMaintenance.GetEntityInfo(entityType);if(entityType.GetCustomAttribute<SplitTableAttribute>(true)!=null){//拆分表的操作需要实体类型,而通过反射很难实现//所以,这里将Init方法写在“种子数据类”内部,再传入 db 反射调用varhasInitMethod=seedType.GetMethod("Init");varparameters=newobject[]{db};hasInitMethod?.Invoke(instance,parameters);}else{if(entityInfo.Columns.Any(u=>u.IsPrimarykey)){// 按主键进行批量增加和更新varstorage=dbProvider.StorageableByObject(seedData.ToList()).ToStorage();// 先修改再插入,否则会更新修改时间字段if(seedType.GetCustomAttribute<IgnoreUpdateSeedAttribute>()==null)// 有忽略更新种子特性时则不更新{intupdateCount=storage.AsUpdateable.IgnoreColumns(entityInfo.Columns.Where(u=>u.PropertyInfo.GetCustomAttribute<IgnoreUpdateSeedColumnAttribute>()!=null).Select(u=>u.PropertyName).ToArray()).ExecuteCommand();Console.WriteLine($" 修改{updateCount}/{seedData.Count()}条记录");}intinsertCount=storage.AsInsertable.ExecuteCommand();if(insertCount>0){Console.WriteLine($"添加数据{entityInfo.DbTableName}({++count}/{sum},种子数据:{seedData.Count()}) 插入{insertCount}条记录");}}else{// 无主键则只进行插入if(!dbProvider.Queryable(entityInfo.DbTableName,entityInfo.DbTableName).Any())dbProvider.InsertableByObject(seedData.ToList()).ExecuteCommand();}}}_isHandlingSeedData=false;}}
← 返回列表