【问题标题】:Can EF Code First work with LocalDB in a ClickOnce application?EF Code First 可以在 ClickOnce 应用程序中与 LocalDB 一起使用吗?
【发布时间】:2016-01-06 03:18:25
【问题描述】:

所以,我正在尝试 EF Code First,以便我可以让代码驱动更新到数据库。我正在使用 LocalDB 开发 ClickOnce 应用程序,因此认为这可能是对我来说最好的解决方案,因为否则对 MDF 文件的更改将导致它在部署时在客户端上被覆盖,从而丢失之前输入的所有内容。

但是,我现在正面临着围绕 Code First 迁移的所有新问题。我已经完成了Code First Migrations on MSDN,并设法创建了初始Configuration,以及初始数据库创建。

当我尝试进行第一次实际迁移时,问题就开始了。我向其中一个模型添加了一个字段,并尝试进行显式迁移以在下次发布时处理该架构更改。嗯……

PM> Add-Migration AddIsPercentField

无法生成显式迁移,因为以下显式迁移处于挂起状态:[201601052011180_InitialCreate]。在尝试生成新的显式迁移之前应用挂起的显式迁移。

好的...我将运行更新并重试:

PM> 更新数据库

指定“-Verbose”标志以查看应用于目标数据库的 SQL 语句。
应用显式迁移:[201601052011180_InitialCreate]。
应用显式迁移:201601052011180_InitialCreate。
无法更新数据库以匹配当前模型,因为存在待处理的更改并且自动迁移已禁用。将挂起的模型更改写入基于代码的迁移或启用自动迁移。将 DbMigrationsConfiguration.AutomaticMigrationsEnabled 设置为 true 以启用自动迁移。
您可以使用 Add-Migration 命令将挂起的模型更改写入基于代码的迁移。

PM> Add-Migration AddIsPercentField

无法生成显式迁移,因为以下显式迁移处于挂起状态:[201601052011180_InitialCreate]。在尝试生成新的显式迁移之前应用挂起的显式迁移。

这很熟悉,因为这是它刚刚告诉我的错误(公然撒谎?)。好吧,也许如果我撤消更改并再次更新,它将进入有效状态:

PM> 更新数据库

指定“-Verbose”标志以查看应用于目标数据库的 SQL 语句。
应用显式迁移:[201601052011180_InitialCreate]。
应用显式迁移:201601052011180_InitialCreate。
运行种子方法。

好的,这次没有警告。应该是金色的。字段添加回来,项目重建。我们开始:

PM> Add-Migration AddIsPercentField

无法生成显式迁移,因为以下显式迁移处于挂起状态:[201601052011180_InitialCreate]。在尝试生成新的显式迁移之前应用挂起的显式迁移。

那么...实际上有没有一种可行的方法来为第一次之外的任何更改生成显式迁移?

编辑:我相信我在这方面取得了一些进展。我确实注意到在运行Update-Database 后,我的.mdf 中没有生成__MigrationHistory 表,尽管它说一切都完成得很好。我相信问题实际上在于本地数据库在应用程序中的工作方式。连接字符串引用AttachDbFilename=|DataDirectory|。我认为正在发生的事情是它正在临时部署 .mdf,更新该 临时 部署,因此最终不会提交更改。

我正在研究我想到的解决方案,即针对放置在静态位置的空白 .mdf 副本进行迁移,以便使用静态 .mdf 跟踪和确定更改,而空白的 .mdf 将通过部署发送给客户端。

【问题讨论】:

  • 第一次迁移后是否在_MigrationHistory中插入了一条记录?您是否在配置文件中设置了 ContextKey? Add-Migration AddIsPercentField -Force 是否有效?既然你来得早,也许把所有东西都撕下来再试一次。删除代码迁移和数据库表,重新启用等
  • @SteveGreene 首先,感谢您的意见!不设置ContextKey,但默认应该没问题,因为只有一个数据库和一个应用程序,因为它是LocalDB。 -Force 参数没有帮助,已经尝试过了。我确实取得了一些进展,一旦有时间我会尽快更新我的问题。

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


【解决方案1】:

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

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

我到达的解决方案是拥有两个 .mdf 文件。空白的一个,用于部署,第二个,我将与 Code First Migrations 交互。所以,我有构建操作Content 的初始MyData.mdf,以及构建操作None 的第二个MyDataDesignTime.mdf。 (不应部署“设计时”迁移数据库。)

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

【讨论】:

    猜你喜欢
    • 2018-10-07
    • 1970-01-01
    • 1970-01-01
    • 2014-09-28
    • 1970-01-01
    • 2011-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多