【问题标题】:EF 4.1 messing things up. Has FK naming strategy changed?EF 4.1 搞砸了。 FK 命名策略有变化吗?
【发布时间】:2011-03-17 19:56:23
【问题描述】:

我刚刚安装了新的 Entity Framework 4.1 NuGet 包,因此按照 NuGet 指令替换了 EFCodeFirst this article of Scott Hanselman

现在,想象一下以下模型:

public class User
{
    [Key]
    public string UserName { get; set; }
    // whatever
}

public class UserThing
{
    public int ID { get; set; }
    public virtual User User { get; set; }
    // whatever
}

上一个 EFCodeFirst 版本在名为 UserUserNameUserThing 表中生成了一个外键。

安装新版本并运行后出现以下错误:

Invalid column name 'User_UserName'

这当然意味着新版本有不同的 FK 命名策略。这在所有其他表和列中是一致的:无论 FK EFCodeFirst 命名为 AnyOldForeignKeyID EF 4.1 想要调用 AnyOldForeignKey_ID(注意下划线)。

我不介意用下划线命名 FK,但在这种情况下,这意味着必须要么不必要地丢弃数据库并重新创建它,要么不必要地重命名所有 FK。

有人知道为什么 FK 命名约定发生了变化,以及是否可以在不使用 Fluent API 的情况下进行配置

【问题讨论】:

    标签: ef-code-first entity-framework-4.1


    【解决方案1】:

    不幸的是,在此版本中没有实现的功能之一是能够在 Code First 中添加自定义约定:

    http://blogs.msdn.com/b/adonet/archive/2011/03/15/ef-4-1-release-candidate-available.aspx

    如果您不想使用 fluent API 来配置列名(我不怪您),那么最直接的方法可能是使用 sp_rename

    【讨论】:

    • 谢谢,我也看到了那篇文章……可惜,为什么一开始就变了?
    • 我更新了我的答案,包括关于如何解决这个问题的建议,它并不漂亮,但它可能是最简单的。我不知道为什么改变了约定。这是早期采用者的缺点之一,他们可以像这样改变你的东西。当我在我的个人网站上使用它时,它也影响了我,更糟糕的是,我编写了一些自己的约定,所以我现在真的很迷茫。
    • 所以您建议 sp_rename 将当前 FK 重命名为新约定所期望的名称?我想它必须这样做,谢谢!
    【解决方案2】:

    你为什么不做以下事情?

      public class User
      {
        [Key]
        public string UserName { get; set; }
        // whatever
      }
    
      public class UserThing
      {
        public int ID { get; set; }
        public string UserUserName { get; set; }
        [ForeignKey("UserUserName")]
        public virtual User User { get; set; }
        // whatever
      }
    

    或者,如果您不想将 UserUserName 属性添加到 UserThing,则使用 fluent API,如下所示:

    // class User same as in question
    // class UserThing same as in question
    
    public class MyContext : DbContext
    {
      public MyContext()
        : base("MyCeDb") { }
      public DbSet<User> Users { get; set; }
      public DbSet<UserThing> UserThings { get; set; }
    
      protected override void OnModelCreating(DbModelBuilder modelBuilder)
      {
        modelBuilder.Entity<UserThing>()
          .HasOptional(ut => ut.User)    // See if HasRequired fits your model better
          .WithMany().Map(u => u.MapKey("UserUserName"));
      }
    }
    

    【讨论】:

    • @Andre - 我已经尝试过 [ForeignKey] 属性,但它给了我一个错误。这同样好,因为我真的不想用它来混淆我的代码。我特别要求不使用流利的api的解决方案;)
    • @Sergi:我不知道您在尝试时遇到了什么错误,但我根据您提供的模型测试了两种实现,并且都可以正常工作。您有一个适合您的答案,我只是想再添加两个选项,说明人们如何使用与内置约定不同的外键列。
    • @Sergi:很高兴。我希望它可以节省一些时间。
    • @Claude 为什么所有东西都叫 FLUENT? API 很流畅,我明白这一点。但为什么每个人都对它如此着迷?为什么不通过声明(属性)和代码(流利)来调用它。
    • @user288291:我不是克劳德,但我很乐意回答你的问题。本质上,有几种方法可以设计不符合“流畅”要求的以代码为中心的 API。 Fluent API 的构建使代码可以从外向内或自上而下读取。 API 也可以设计为由内向外读取,或作为状态机等。根据 Fowler 和 Evans 的说法,Fluent API 背后的理念是它们应该像一种语言一样读取。 Fowler 将它们称为 [types of] 内部 DSL。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多