所以,我尝试了EF Code First,这样我就可以对数据库进行代码驱动更新了。我正在使用LocalDB处理ClickOnce应用程序,因此对我来说这可能是最好的解决方案,因为否则对MDF文件的更改将导致在部署时在客户端上覆盖它,从而丢失之前输入的所有内容。 / p>
但是,我现在能够公平地分享Code First Migrations的所有新问题。我已经跟进了Code First Migrations on MSDN,我设法创建了初始Configuration
,并创建了初始数据库。
当我尝试进行第一次实际迁移时问题就开始了。我在我的一个模型中添加了一个单独的字段,并尝试进行显式迁移以在下次发布时处理该模式更改。嗯......
PM>添加迁移AddIsPercentField
由于以下显式迁移未决,因此无法生成显式迁移:[201601052011180_InitialCreate]。在尝试生成新的显式迁移之前应用挂起的显式迁移。
好的......我将运行更新并再试一次:
PM>更新数据库
指定' -Verbose'用于查看应用于目标数据库的SQL语句的标志 应用显式迁移:[201601052011180_InitialCreate]。
应用显式迁移:201601052011180_InitialCreate。
无法更新数据库以匹配当前模型,因为存在挂起的更改并且已禁用自动迁移。将挂起的模型更改写入基于代码的迁移或启用自动迁移。将DbMigrationsConfiguration.AutomaticMigrationsEnabled设置为true以启用自动迁移 您可以使用Add-Migration命令将挂起的模型更改写入基于代码的迁移。PM>添加迁移AddIsPercentField
由于以下显式迁移未决,因此无法生成显式迁移:[201601052011180_InitialCreate]。在尝试生成新的显式迁移之前应用挂起的显式迁移。
那个熟悉的,因为它之前告诉我的错误(公然谎言?)。好吧,也许如果我撤消我的更改并再次更新,它将转移到有效状态:
PM>更新数据库
指定' -Verbose'用于查看应用于目标数据库的SQL语句的标志 应用显式迁移:[201601052011180_InitialCreate]。
应用显式迁移:201601052011180_InitialCreate。
运行种子方法。
好的,这次没有警告。应该是金色的。 Field添加回来,项目重建。我们走了:
PM>添加迁移AddIsPercentField
由于以下显式迁移未决,因此无法生成显式迁移:[201601052011180_InitialCreate]。在尝试生成新的显式迁移之前应用挂起的显式迁移。
那么...... 实际上是为第一个以外的任何变化生成显式迁移的工作方式吗?
编辑:我相信,我在这方面取得了一些进展。我注意到在运行__MigrationHistory
后我的.mdf中没有生成Update-Database
表,尽管它表示一切都已完成。我认为问题实际上是关于本地数据库如何在应用程序中工作。连接字符串引用AttachDbFilename=|DataDirectory|
。我的想法是,它正在临时部署.mdf,更新临时部署,因此最终不会提交更改。
我正在研究一个我想到的解决方案,即将迁移工作放在静态位置的空白.mdf副本中,以便静态.mdf用于跟踪和确定更改,而空白.mdf将是部署客户端的内容。
答案 0 :(得分:0)
我发现问题的根源在于控制台命令实际上无法进行更改,从而跟踪迁移到我的数据文件。这是由于引用部署位置的数据文件的连接字符串,因此正在更新的文件只是暂时的。
这部分是一件好事,因为在我的项目中使用Code First Migrations的重点是避免在发布时对我的.mdf(它应该只是作为占位符保持空白)的哈希签名更改,所以以前版本的数据永远不会被覆盖和丢弃。然而,这也引入了一个明显的(回想起来)问题,即由于从未有__MigrationHistory
表,EF无法跟踪变化。
我到达的解决方案是有两个.mdf文件。空白的,用于部署,第二个,我将与Code First Migrations交互。因此,我有Build MyData.mdf
的初始Content
和Build Action MyDataDesignTime.mdf
的第二None
。 (不应部署“设计时”迁移数据库。)
使用这种方法,我发现我现在可以成功地进行迁移,调用Update-Database
和Add-Migration
,确保通过-ConnectionString
参数传递AttachDbFilename
指向我设计时数据库的完整路径。
后来,懒得在每个迁移命令上提供一个长-ConnectionString
参数,我将设计时间路径添加到我的配置连接字符串,并更新了我的DbContext
,以便它使用设计时间路径最初,但我会在运行时开始使用我的实际目标数据文件进行更改:
public partial class MyData : DbContext
{
public const string DesignTimeConnection = "MyDataConnectionStringDesignTime";
public static string ConnectionName { get; set; } = DesignTimeConnection;
public MyData()
: base("name=" + ConnectionName)
{
}
...
}
在应用程序初始化时:
MyData.ConnectionName = "MyDataConnectionString";
这很有效,而且对我来说更简单。但是,我留下的一个小问题是我有一个完整的静态路径,它只适用于我在app.config文件中留下的环境。目前不是一个问题,因为我是这个项目的唯一开发者,但这是一种我不满意的代码味道。是否有一些我可以使用的路径变量,这样它仍然指向实际的设计时数据(不是任何临时的,已部署的文件),而是相对于活动的,打开的项目呢?