zoukankan      html  css  js  c++  java
  • WTM框架在开发过程中如何动态迁移表和创建表

    官方迁移方法:https://wtmdoc.walkingtec.cn/#/Data/Migration

    但是在实际开发过程中使用Add-Migration 方法迁移会发现,把系统内置的表也全部带出来了,自己需要手动删。

    在参看官方的源码后发现作者也想到了这个问题(还在开发当中,可以查看EmptyContext),毕竟这不优雅,但是在稳定版本内没有合适的解决方式,故我借鉴了一下(抄袭)。

    public partial class EmptyContext : DbContext, IDataContext
        {
            /// <summary>
            /// Commited
            /// </summary>
            public bool Commited { get; set; }
    
            /// <summary>
            /// IsFake
            /// </summary>
            public bool IsFake { get; set; }
    
            /// <summary>
            /// CSName
            /// </summary>
            public string CSName { get; set; }
    
            public DBTypeEnum DBType { get; set; }
    
            /// <summary>
            /// FrameworkContext
            /// </summary>
            public EmptyContext()
            {
                CSName = "default";
                DBType = DBTypeEnum.SqlServer;
            }
    
            /// <summary>
            /// FrameworkContext
            /// </summary>
            /// <param name="cs"></param>
            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 });
            }
            /// <summary>
            /// 将一个实体设为填加状态
            /// </summary>
            /// <param name="entity">实体</param>
            public void AddEntity<T>(T entity) where T : TopBasePoco
            {
                this.Entry(entity).State = EntityState.Added;
            }
    
            /// <summary>
            /// 将一个实体设为修改状态
            /// </summary>
            /// <param name="entity">实体</param>
            public void UpdateEntity<T>(T entity) where T : TopBasePoco
            {
                this.Entry(entity).State = EntityState.Modified;
            }
    
            /// <summary>
            /// 将一个实体的某个字段设为修改状态,用于只更新个别字段的情况
            /// </summary>
            /// <typeparam name="T">实体类</typeparam>
            /// <param name="entity">实体</param>
            /// <param name="fieldExp">要设定为修改状态的字段</param>
            public void UpdateProperty<T>(T entity, Expression<Func<T, object>> fieldExp)
                where T : TopBasePoco
            {
                var set = this.Set<T>();
                if (set.Local.AsQueryable().CheckID(entity.GetID()).FirstOrDefault() == null)
                {
                    set.Attach(entity);
                }
                this.Entry(entity).Property(fieldExp).IsModified = true;
            }
    
            /// <summary>
            /// UpdateProperty
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="entity"></param>
            /// <param name="fieldName"></param>
            public void UpdateProperty<T>(T entity, string fieldName)
                where T : TopBasePoco
            {
                var set = this.Set<T>();
                if (set.Local.AsQueryable().CheckID(entity.GetID()).FirstOrDefault() == null)
                {
                    set.Attach(entity);
                }
                this.Entry(entity).Property(fieldName).IsModified = true;
            }
    
            /// <summary>
            /// 将一个实体设定为删除状态
            /// </summary>
            /// <param name="entity">实体</param>
            public void DeleteEntity<T>(T entity) where T : TopBasePoco
            {
                var set = this.Set<T>();
                if (set.Local.AsQueryable().CheckID(entity.GetID()).FirstOrDefault() == null)
                {
                    set.Attach(entity);
                }
                set.Remove(entity);
            }
    
            /// <summary>
            /// CascadeDelete
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="entity"></param>
            public void CascadeDelete<T>(T entity) where T : TopBasePoco, ITreeData<T>
            {
                if (entity != null && entity.ID != Guid.Empty)
                {
                    var set = this.Set<T>();
                    var entities = set.Where(x => x.ParentId == entity.ID).ToList();
                    if (entities.Count > 0)
                    {
                        foreach (var item in entities)
                        {
                            CascadeDelete(item);
                        }
                    }
                    DeleteEntity(entity);
                }
            }
    
            /// <summary>
            /// GetCoreType
            /// </summary>
            /// <param name="t"></param>
            /// <returns></returns>
            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;
                }
            }
    
            /// <summary>
            /// OnModelCreating
            /// </summary>
            /// <param name="modelBuilder"></param>
            protected override void OnModelCreating(ModelBuilder modelBuilder)
            {
    
            }
    
            /// <summary>
            /// OnConfiguring
            /// </summary>
            /// <param name="optionsBuilder"></param>
            protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
            {
                switch (DBType)
                {
                    case DBTypeEnum.SqlServer:
                        try
                        {
                            var Configs = GlobalServices.GetRequiredService<Configs>();
                            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<Configs>();//如果是debug模式,将EF生成的sql语句输出到debug输出
                    if (Configs.IsQuickDebug)
                    {
                        optionsBuilder.UseLoggerFactory(LoggerFactory);
                    }
                }
                catch { }
                base.OnConfiguring(optionsBuilder);
            }
    
            public static readonly LoggerFactory LoggerFactory = new LoggerFactory(new[] {
                new DebugLoggerProvider()
            });
    
            /// <summary>
            /// 数据初始化
            /// </summary>
            /// <param name="allModules"></param>
            /// <param name="IsSpa"></param>
            /// <returns>返回true表示需要进行初始化数据操作,返回false即数据库已经存在或不需要初始化数据</returns>
            public async virtual Task<bool> DataInit(object allModules, bool IsSpa)
            {
                bool rv = await Database.EnsureCreatedAsync();
                return rv;
            }
    
            #region 执行存储过程返回datatable
            /// <summary>
            /// 执行存储过程,返回datatable结果集
            /// </summary>
            /// <param name="command">存储过程名称</param>
            /// <param name="paras">存储过程参数</param>
            /// <returns></returns>
            public DataTable RunSP(string command, params object[] paras)
            {
                return Run(command, CommandType.StoredProcedure, paras);
            }
            #endregion
    
            public IEnumerable<TElement> RunSP<TElement>(string command, params object[] paras)
            {
                return Run<TElement>(command, CommandType.StoredProcedure, paras);
            }
    
            #region 执行Sql语句,返回datatable
            public DataTable RunSQL(string sql, params object[] paras)
            {
                return Run(sql, CommandType.Text, paras);
            }
            #endregion
    
            public IEnumerable<TElement> RunSQL<TElement>(string sql, params object[] paras)
            {
                return Run<TElement>(sql, CommandType.Text, paras);
            }
    
    
            #region 执行存储过程或Sql语句返回DataTable
            /// <summary>
            /// 执行存储过程或Sql语句返回DataTable
            /// </summary>
            /// <param name="sql">存储过程名称或Sql语句</param>
            /// <param name="commandType">命令类型</param>
            /// <param name="paras">参数</param>
            /// <returns></returns>
            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<TElement> Run<TElement>(string sql, CommandType commandType, params object[] paras)
            {
                IEnumerable<TElement> entityList = new List<TElement>();
                DataTable dt = Run(sql, commandType, paras);
                entityList = EntityHelper.GetEntityList<TElement>(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 DbSet<School> Schools { get; set; }
            public MEContext(string cs, DBTypeEnum dbtype)
                 : base(cs, dbtype)
            {
    
            }
    
        }
    
        /// <summary>
        /// 为EF的Migration准备的辅助类,填写完整连接字符串和数据库类型
        /// 就可以使用Add-Migration和Update-Database了
        /// </summary>
        public class DataContextFactory : IDesignTimeDbContextFactory<MEContext>
        {
            public MEContext CreateDbContext(string[] args)
            {
                var dc= new MEContext("连接字符串",
                    DBTypeEnum.MySql);
                return dc;
            }
        }

    然后敲指令

    Add-Migration Initia-IgnoreChanges -Context MEContext  //先生成迁移的代码

    Update-Database//然后迁移

  • 相关阅读:
    Redis学习
    extractor
    Linux fork exec等
    Linux kill 命令
    GCC参数使用
    Shell 参数(2) --解析命令行参数工具:getopts/getopt
    Shell 参数(1)
    shell 中并发执行
    Linux 下新增用户的流程
    Linux 安全rm
  • 原文地址:https://www.cnblogs.com/RainbowInTheSky/p/12306827.html
Copyright © 2011-2022 走看看