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//然后迁移
WTM框架在开发过程中如何动态迁移表和创建表的更多相关文章
- 基于vue框架项目开发过程中遇到的问题总结(三)
这次遇到的一个问题困扰了我很久很久,大致就是vue路由的addRoutes方法的使用,每次在调用了这个之后router对象中并没有将路由添加进去,接下来,我一步一步的分析原因及解决方法(个人见解,仅供 ...
- 基于vue框架项目开发过程中遇到的问题总结(二)
1.mouseup事件丢失 查看了网上资料,造成mouseup事件丢失有两种原因: (1)触发了浏览器的drag事件 (2)由于鼠标离开了操作的区域,触发了mouseleave事件导致mouseup丢 ...
- 基于vue框架项目开发过程中遇到的问题总结(一)
(一)关于computed修改data里变量的值 问题:computed里是不能直接修改data里变量的值,否则在git commit 时会报错 解决:在computed里使用get和set来进行获取 ...
- YII2框架动态创建表模型
YII2框架动态创建表模型 在YII2中,每个表对应一个model类 在开发过程中,我们在填写一个大型表单的时候,表单里有N个select下拉列表,每个下拉select来自于不同的表: 如果要在程序里 ...
- Asp.Net MVC Web API 中Swagger教程,使用Swagger创建Web API帮助文件
什么是Swagger? Swagger 是一个规范和完整的框架,用于生成.描述.调用和可视化 RESTful 风格的 Web 服务.总体目标是使客户端和文件系统作为服务器以同样的速度来更新.文件的方法 ...
- Django用户认证模块中继承AbstractUser与AbstractBaseUser重写User表的区别
AbstractUser和AbstractBaseUser看起来十分相似,如果你不熟悉djiango的auth重写User,那你很容易弄错,导致一堆bug. 我们查看AbstractUser的源码得知 ...
- 在快速自定义的NopCommerce中使用实体框架(EF)代码优先迁移
我看到很多nopCommerce论坛的用户问他们如何使用Entity Framework(EF)代码优先迁移来自定义nopCommerce,添加新的字段和entites核心.我实际上在做nopComm ...
- Hyper-V动态迁移中?小心性能损失
动态迁移是虚拟化技术的一个标志,它允许虚拟机在服务器间进行动态迁移.调节负载平衡.性能管理.备灾管理和数据中心维护.Windows Server 2012 R2中的Hyper-V动态迁移默认功能具备相 ...
- Winform开发框架之客户关系管理系统(CRM)的开发总结系列2-基于框架的开发过程
在上篇随笔<Winform开发框架之客户关系管理系统(CRM)的开发总结系列1-界面功能展示>中介绍了我的整个CRM系统的概貌,本篇继续本系列的文章,介绍如何基于我的<winform ...
随机推荐
- Day1-C-CF-1144A
简述:给你一串字符,判断是否由连续字母构成且每个字符只出现一次 思路:用set直接储存,判断size和初末位置字母与size的关系即可 代码: #include<iostream> #in ...
- redis 之 redis主从复制
Redis集群中的数据库复制是通过主从同步来实现的 主节点(Master)把数据分发给从节点(Slave) 主从同步的好处在于高可用,Redis节点有冗余设计 主从复制的原理:1. 从服务器向主服务器 ...
- 设计模式课程 设计模式精讲 13-2 享元模式coding
1 代码演练 1.1 代码演练1 1 代码演练 1.1 代码演练1 需求: 每周由随机部门经历做报告: 重点关注: a 该案例是单例模式和享元模式共同使用 b 外部传入的department是外部状态 ...
- java实现邮箱发送邮件
第一步:封装发件人账号密码 import javax.mail.Authenticator;import javax.mail.PasswordAuthentication; /** * 发件人账号密 ...
- vb.net自学完整版
https://m.book118.com/html/2016/1203/67671992.shtm
- linux下的文件操作
彻底删除文件 rm -rf + [文件目录 可相对可绝对] 是彻底删除而且linux无回收站 创建文件 touch + [文件名] 创建文件夹 mkdir + [文件夹名] 文件提权:chmod 77 ...
- 树莓派frp添加为服务管理
1.下载frp https://github.com/fatedier/frp/releases 我是1代的B+,下载arm版的,新的可以用arm64的 frp_0.29.0_linux_arm.ta ...
- 《Netlogo多主体建模入门》笔记4
4- 从Langton的蚂蚁看Turtle与Patch的交互 这只蚂蚁从10000步开始,就会自发地 “建桥” Turtle与Patch就好比是,一个方块和一个格子的关系. 一个格子上可以 ...
- app开屏广告
最近公司有个需求需要做app开屏广告(跳转到不同的页面)--下面是app开屏广告的处理 1.管理后台效果图 (1)广告链接--商品详情 (2)广告链接--关联模块 (3)广告链接--消息富文本 (4) ...
- 【Go语言系列】2.1、Go语言基本程序结构:注释
注释在程序中的作用是对程序进行注解和说明,便于对源码的阅读.在源码中适当地添加注释,能够提高源码的可读性. Go语言的注释主要分成两类,分别是单行注释和多行注释. 单行注释: //单行注释 多行注释: ...