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 ...
随机推荐
- windows下pycharm连接vagrant的python环境
- reactor---元数据驱动的表单
class NameForm extends React.Component { constructor(props) { super(props); this.state = { ...
- 吴裕雄 Bootstrap 前端框架开发——Bootstrap 按钮:让按钮看起来像个链接 (仍然保留按钮行为)
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...
- S7-300 与TP900 组态 棒图 量表 滚动条 滚动条设置的值通过IO输出域显示出来
切换编程语言 注意 一定要 先选中 某一个组织块 例如 OB1 然后单击 菜单 编辑 切换编程语言 组态 300 PLC 的CPU 点击 SIMENSE LOGO 查看 循环 中断 OB35 可以 在 ...
- java、mysql、oracle、pgsql数据类型对应关系
看不清 请 Ctrl+鼠标滚轮 放大页面
- osg 线框模式,点模式切换
需要加 viewer.addEventHandler(new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet ...
- mutiset的简单介绍转载
原文链接:https://blog.csdn.net/sodacoco/article/details/84798621 c++语言中,multiset是<set>库中一个非 ...
- 常见加密解密 -- pycryptodomex库
安装 windows pip install pycryptodomex ubuntu pip install pycryptodome 加密方式 单向加密:MD5 只能对数据进行加密,而不能解密 对 ...
- vi/vim编辑器基本操作
一.vi/vim的三种模式 vi编辑器有三种模式:命令模式(command mode).插入模式(Insert mode).底行模式(last line mode). 就是你直接用命令(vi 文件名 ...
- docker-lnmp 多容器部署 Laravel 方案分享(转)
docker lnmp 多容器部署方案.完全基于 docker 官方镜像,遵循最佳实践,一容器一进程. github 项目地址 https://github.com/March7/docker-lnm ...