官方迁移方法:https://wtmdoc.walkingtec.cn/#/Data/Migration
但是在实际开发过程中使用Add-Migration 方法迁移会发现,把系统内置的表也全部带出来了,自己需要手动删。
在参看官方的源码后发现作者也想到了这个问题(还在开发当中,可以查看EmptyContext),毕竟这不优雅,但是在稳定版本内没有合适的解决方式,故我借鉴了一下(抄袭)。
public partial class EmptyContext : DbContext, IDataContext { ////// Commited /// public bool Commited { get; set; } ////// IsFake /// public bool IsFake { get; set; } ////// CSName /// public string CSName { get; set; } public DBTypeEnum DBType { get; set; } ////// FrameworkContext /// public EmptyContext() { CSName = "default"; DBType = DBTypeEnum.SqlServer; } ////// FrameworkContext /// /// public EmptyContext(string cs) { CSName = cs; } public EmptyContext(string cs, DBTypeEnum dbtype) { CSName = cs; DBType = dbtype; } public IDataContext CreateNew() { return (IDataContext)this.GetType().GetConstructor(new Type[] { typeof(string), typeof(DBTypeEnum) }).Invoke(new object[] { CSName, DBType }); } public IDataContext ReCreate() { return (IDataContext)this.GetType().GetConstructor(new Type[] { typeof(string), typeof(DBTypeEnum) }).Invoke(new object[] { CSName, DBType }); } ////// 将一个实体设为填加状态 /// /// 实体 public void AddEntity(T entity) where T : TopBasePoco { this.Entry(entity).State = EntityState.Added; } /// /// 将一个实体设为修改状态 /// /// 实体 public void UpdateEntity(T entity) where T : TopBasePoco { this.Entry(entity).State = EntityState.Modified; } /// /// 将一个实体的某个字段设为修改状态,用于只更新个别字段的情况 /// ///实体类 /// 实体 /// 要设定为修改状态的字段 public void UpdateProperty(T entity, Expression > fieldExp) where T : TopBasePoco { var set = this.Set (); if (set.Local.AsQueryable().CheckID(entity.GetID()).FirstOrDefault() == null) { set.Attach(entity); } this.Entry(entity).Property(fieldExp).IsModified = true; } /// /// UpdateProperty /// ////// /// public void UpdateProperty (T entity, string fieldName) where T : TopBasePoco { var set = this.Set (); if (set.Local.AsQueryable().CheckID(entity.GetID()).FirstOrDefault() == null) { set.Attach(entity); } this.Entry(entity).Property(fieldName).IsModified = true; } /// /// 将一个实体设定为删除状态 /// /// 实体 public void DeleteEntity(T entity) where T : TopBasePoco { var set = this.Set (); if (set.Local.AsQueryable().CheckID(entity.GetID()).FirstOrDefault() == null) { set.Attach(entity); } set.Remove(entity); } /// /// CascadeDelete /// ////// public void CascadeDelete (T entity) where T : TopBasePoco, ITreeData { if (entity != null && entity.ID != Guid.Empty) { var set = this.Set (); var entities = set.Where(x => x.ParentId == entity.ID).ToList(); if (entities.Count > 0) { foreach (var item in entities) { CascadeDelete(item); } } DeleteEntity(entity); } } /// /// GetCoreType /// /// ///public Type GetCoreType(Type t) { if (t != null && t.IsNullable()) { if (!t.GetTypeInfo().IsValueType) { return t; } else { if ("DateTime".Equals(t.GenericTypeArguments[0].Name)) { return typeof(string); } return Nullable.GetUnderlyingType(t); } } else { if ("DateTime".Equals(t.Name)) { return typeof(string); } return t; } } /// /// OnModelCreating /// /// protected override void OnModelCreating(ModelBuilder modelBuilder) { } ////// OnConfiguring /// /// protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { switch (DBType) { case DBTypeEnum.SqlServer: try { var Configs = GlobalServices.GetRequiredService(); if (Configs.IsOldSqlServer == true) { optionsBuilder.UseSqlServer(CSName, op => op.UseRowNumberForPaging()); } else { optionsBuilder.UseSqlServer(CSName); } } catch { optionsBuilder.UseSqlServer(CSName, op => op.UseRowNumberForPaging()); } break; case DBTypeEnum.MySql: optionsBuilder.UseMySql(CSName); break; case DBTypeEnum.PgSql: optionsBuilder.UseNpgsql(CSName); break; case DBTypeEnum.Memory: optionsBuilder.UseInMemoryDatabase(CSName); break; case DBTypeEnum.SQLite: optionsBuilder.UseSqlite(CSName); break; case DBTypeEnum.Oracle: optionsBuilder.UseOracle(CSName); break; default: break; } try { var Configs = GlobalServices.GetRequiredService ();//如果是debug模式,将EF生成的sql语句输出到debug输出 if (Configs.IsQuickDebug) { optionsBuilder.UseLoggerFactory(LoggerFactory); } } catch { } base.OnConfiguring(optionsBuilder); } public static readonly LoggerFactory LoggerFactory = new LoggerFactory(new[] { new DebugLoggerProvider() }); /// /// 数据初始化 /// /// /// ///返回true表示需要进行初始化数据操作,返回false即数据库已经存在或不需要初始化数据 public async virtual TaskDataInit(object allModules, bool IsSpa) { bool rv = await Database.EnsureCreatedAsync(); return rv; } #region 执行存储过程返回datatable /// /// 执行存储过程,返回datatable结果集 /// /// 存储过程名称 /// 存储过程参数 ///public DataTable RunSP(string command, params object[] paras) { return Run(command, CommandType.StoredProcedure, paras); } #endregion public IEnumerable RunSP (string command, params object[] paras) { return Run (command, CommandType.StoredProcedure, paras); } #region 执行Sql语句,返回datatable public DataTable RunSQL(string sql, params object[] paras) { return Run(sql, CommandType.Text, paras); } #endregion public IEnumerable RunSQL (string sql, params object[] paras) { return Run (sql, CommandType.Text, paras); } #region 执行存储过程或Sql语句返回DataTable /// /// 执行存储过程或Sql语句返回DataTable /// /// 存储过程名称或Sql语句 /// 命令类型 /// 参数 ///public DataTable Run(string sql, CommandType commandType, params object[] paras) { DataTable table = new DataTable(); switch (this.DBType) { case DBTypeEnum.SqlServer: SqlConnection con = this.Database.GetDbConnection() as SqlConnection; SqlDataAdapter adapter = new SqlDataAdapter(); using (SqlCommand cmd = new SqlCommand(sql, con)) { adapter.SelectCommand = cmd; cmd.CommandTimeout = 2400; cmd.CommandType = commandType; if (paras != null) { foreach (var param in paras) cmd.Parameters.Add(param); } adapter.Fill(table); adapter.SelectCommand.Parameters.Clear(); } break; case DBTypeEnum.MySql: MySqlConnection mySqlCon = this.Database.GetDbConnection() as MySqlConnection; using (MySqlCommand cmd = new MySqlCommand(sql, mySqlCon)) { if (mySqlCon.State == ConnectionState.Closed) { mySqlCon.Open(); } cmd.CommandTimeout = 2400; cmd.CommandType = commandType; if (paras != null) { foreach (var param in paras) cmd.Parameters.Add(param); } MySqlDataReader dr = cmd.ExecuteReader(); table.Load(dr); dr.Close(); mySqlCon.Close(); } break; case DBTypeEnum.PgSql: Npgsql.NpgsqlConnection npgCon = this.Database.GetDbConnection() as Npgsql.NpgsqlConnection; using (Npgsql.NpgsqlCommand cmd = new Npgsql.NpgsqlCommand(sql, npgCon)) { if (npgCon.State == ConnectionState.Closed) { npgCon.Open(); } cmd.CommandTimeout = 2400; cmd.CommandType = commandType; if (paras != null) { foreach (var param in paras) cmd.Parameters.Add(param); } Npgsql.NpgsqlDataReader dr = cmd.ExecuteReader(); table.Load(dr); dr.Close(); npgCon.Close(); } break; case DBTypeEnum.SQLite: case DBTypeEnum.Oracle: var connection = this.Database.GetDbConnection(); var isClosed = connection.State == ConnectionState.Closed; if (isClosed) { connection.Open(); } using (var command = connection.CreateCommand()) { command.CommandText = sql; command.CommandTimeout = 2400; command.CommandType = commandType; if (paras != null) { foreach (var param in paras) command.Parameters.Add(param); } using (var reader = command.ExecuteReader()) { table.Load(reader); } } if (isClosed) { connection.Close(); } break; } return table; } #endregion public IEnumerable Run (string sql, CommandType commandType, params object[] paras) { IEnumerable entityList = new List (); DataTable dt = Run(sql, commandType, paras); entityList = EntityHelper.GetEntityList (dt); return entityList; } public object CreateCommandParameter(string name, object value, ParameterDirection dir) { object rv = null; switch (this.DBType) { case DBTypeEnum.SqlServer: rv = new SqlParameter(name, value) { Direction = dir }; break; case DBTypeEnum.MySql: rv = new MySqlParameter(name, value) { Direction = dir }; break; case DBTypeEnum.PgSql: rv = new NpgsqlParameter(name, value) { Direction = dir }; break; case DBTypeEnum.SQLite: rv = new SqliteParameter(name, value) { Direction = dir }; break; case DBTypeEnum.Oracle: rv = new OracleParameter(name, value) { Direction = dir }; break; } return rv; } }
使用的时候
public class DataContext : FrameworkContext { public DataContext(string cs, DBTypeEnum dbtype) : base(cs, dbtype) { } } public class MEContext : EmptyContext { public DbSetSchools { get; set; } public MEContext(string cs, DBTypeEnum dbtype) : base(cs, dbtype) { } } /// /// 为EF的Migration准备的辅助类,填写完整连接字符串和数据库类型 /// 就可以使用Add-Migration和Update-Database了 /// public class DataContextFactory : IDesignTimeDbContextFactory { public MEContext CreateDbContext(string[] args) { var dc= new MEContext("连接字符串", DBTypeEnum.MySql); return dc; } }
然后敲指令
Add-Migration Initia-IgnoreChanges -Context MEContext //先生成迁移的代码
Update-Database//然后迁移