EF Code First可以在ClickOnce应用程序中使用LocalDB吗?

时间:2016-01-06 03:18:25

标签: ef-code-first clickonce localdb ef-migrations

所以,我尝试了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将是部署客户端的内容。

1 个答案:

答案 0 :(得分:0)

我发现问题的根源在于控制台命令实际上无法进行更改,从而跟踪迁移到我的数据文件。这是由于引用部署位置的数据文件的连接字符串,因此正在更新的文件只是暂时的。

这部分是一件好事,因为在我的项目中使用Code First Migrations的重点是避免在发布时对我的.mdf(它应该只是作为占位符保持空白)的哈希签名更改,所以以前版本的数据永远不会被覆盖和丢弃。然而,这也引入了一个明显的(回想起来)问题,即由于从未有__MigrationHistory表,EF无法跟踪变化。

我到达的解决方案是有两个.mdf文件。空白的,用于部署,第二个,我将与Code First Migrations交互。因此,我有Build MyData.mdf的初始Content和Build Action MyDataDesignTime.mdf的第二None。 (不应部署“设计时”迁移数据库。)

使用这种方法,我发现我现在可以成功地进行迁移,调用Update-DatabaseAdd-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文件中留下的环境。目前不是一个问题,因为我是这个项目的唯一开发者,但这是一种我不满意的代码味道。是否有一些我可以使用的路径变量,这样它仍然指向实际的设计时数据(不是任何临时的,已部署的文件),而是相对于活动的,打开的项目呢?