目前,我有一个ERP,它是一个基于Winforms的客户端(带有SQL Server),可以使用ClickOnce在桌面上交付和更新它。
当前版本正在使用Entity Framework 4(基于ObjectContext)和数据库。当数据库架构发生更改时,我对客户端进行更新的方式分为四个步骤:
我发现这个过程对我们来说比较麻烦,对客户来说比较好,他们可以在他们认为合适的时候进行更新,并且在工作中不会被更新打扰(可能涉及到拥有客户)在不想等待软件更新的人面前。
现在,我使用EF6和代码优先的迁移对客户端(仍然是Winforms)进行了几乎完全的重写。
我一直在寻找文档,但是什么也找不到(似乎现在只有Web编程,通常可以同时完成数据库和Web客户端的更新,而不会打扰用户),但是一旦将迁移应用于生产,未更新的客户端将无法再使用该数据库。如果上下文与数据库架构不是最新的,EF将在实例化上下文时进行投诉并引发异常。
特定问题:是否有一种方法可以使EF6代码优先的dbcontext与兼容的内置数据库一起工作,以进行较新的数据库模式迁移?如果是这样,我可以继续做我到目前为止所做的事情。
还有一个(我想)基于oppionion的问题,是否有人想扩展实际答案:是否有更好的方法来处理这种情况?我敢肯定我不是唯一一个遇到此问题的人,但是Google搜索文档所需的关键字范围太广,到目前为止,我的搜索只涉及到Web场景。
我目前在客户端重写的一个阶段上,可以进行重大更改,所以我不在乎解决方案是否会使部分代码复杂化
当应用程序初始化模型数据库时,通过直接调用DbContext.Database.Initialize
或实例化第一个数据库DbContext
,它将检查应用程序中的模型与数据库中的模型是否匹配。
为此,它将计算模型哈希,并将其与__MigrationHistory
表(EdmMetadata
如果已从EF 4.x更新,则存储在表中)中的哈希进行比较。这是在System.Data.Entity.Internal.ModelCompatibilityChecker.CompatibleWithModel
方法中完成的,该方法会接收一个名为的参数,该参数throwIfNoMetadata
恰好false
在内部实现中,因此,如果没有元数据,则不会引发异常。
因此,如果您在初始化数据库之前以某种方式使该表消失,则可以避免该错误。重要的一点是,您必须在不使用的情况下进行此更改DbContext
。如果不存在,数据库将尝试初始化,如果该表存在,它将失败。因此,您可以使用PlainADO.NET
删除表。
考虑到元数据表可以自动创建,例如通过应用迁移。
您还可以ctx.Database.CompatibleWithModel(true)
用来检查数据库元数据是否存在以及是否兼容,以摆脱它。该参数正是throwIfNoMetadata
我上面提到的。
默认的数据库初始值设定项是CreateDatabaseIfNotExists
,它会检查throwIfNoMetadata
设置为的模型兼容性false
。这就是为什么该解决方案有效的原因。但是,如果您实现自己的DB Initializer版本而不运行检查,则它将起作用。
public virtual void InitializeDatabase(TContext context)
{
Check.NotNull(context, "context");
var existence = new DatabaseTableChecker().AnyModelTableExists(context.InternalContext);
if (existence == DatabaseExistenceState.Exists)
{
// If there is no metadata either in the model or in the database, then
// we assume that the database matches the model because the common cases for
// these scenarios are database/model first and/or an existing database.
if (!context.Database.CompatibleWithModel(throwIfNoMetadata: false, existenceState: existence))
{
throw Error.DatabaseInitializationStrategy_ModelMismatch(context.GetType().Name);
}
}
else
{
// Either the database doesn't exist, or exists and is considered empty
context.Database.Create(existence);
Seed(context);
context.SaveChanges();
}
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句