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//然后遷移

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM