【问题标题】:Code-First CTP5 navigational properties generates wrong column namesCode-First CTP5 导航属性生成错误的列名
【发布时间】:2010-12-28 01:12:47
【问题描述】:

我有以下型号和配置:

public class User
{
    public int Id { get; set; }
    public User CreatedBy { get; set; }
    public DateTime? DateCreated { get; set; }
    public string Name { get; set; }
    public string Username { get; set; }
}

public class UserConfiguration : EntityTypeConfiguration<User>
{
    public UserConfiguration()
    {
        this.HasKey(t => t.Id);

        this.HasOptional(u => u.CreatedBy);
        this.Property(u => u.DateCreated);

        this.Property(u => u.Name).HasMaxLength(64);
        this.Property(u => u.Username).HasMaxLength(64);
    }
}

public class SampleContext : DbContext
{

    public IDbSet<User> Users { get; set; }

    public SampleContext(string dbConnection)
        : base(dbConnection)
    {

    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Configurations.Add(new UserConfiguration());
    }
}

我可以很好地处理上下文并添加用户。然后,我查看了 Code First 生成的表,并意识到 CreatedBy 属性不是生成 CreatedById 列,而是生成 UserId 列。如果我添加另一个属性,例如ModifiedBy,它将生成UserId1 等等:

我也尝试使用HasRequired() 进行映射,但该属性仍会生成与实际类型匹配的列名称,而不是属性名称。任何帮助将不胜感激。

【问题讨论】:

    标签: c# entity-framework code-first


    【解决方案1】:

    您基本上想创建一个具有自定义外键列名称的自引用独立关联,这里是执行此操作的流畅 API 代码:

    public UserConfiguration()
    {
        this.HasRequired(u => u.CreatedBy)
            .WithMany()
            .IsIndependent()
            .Map(m => 
            {
                m.MapKey(u => u.Id, "CreatedById");
            });
    }
    

    但是,由于 CTP5 中的错误,此代码会引发异常。因此,目前,您可以使用 MSDN 论坛中建议的解决方法(将您的独立关联更改为 FK 关联并明确命名您的 FK 属性)并将此代码保存到明年的 RTM。

    【讨论】:

    • +1 很高兴知道!我仍然认为这应该是 default 命名约定。似乎存在一些问题,例如不支持 true 枚举,不允许通过继承进行配置(请参阅我在 MSDN 上的一篇文章)等。不过,我会将其保存为 RTM!谢谢:)
    • 没问题 :) 顺便说一句,我找不到你关于“继承配置”的帖子,你能给我提供链接吗?
    • 感谢您的链接。顺便说一句,我已经开始了关于继承映射和 EF Code First CTP5 的系列文章,您可能会发现它很有用:weblogs.asp.net/manavi/archive/2010/12/24/…
    【解决方案2】:

    我越过posted this on the MSDN forums,我想到目前为止,这是设计使然。所有导航属性都会为列名生成类型名称 + Id。对我来说,这是代码优先的基本设计缺陷。生成的名称甚至不反映该列(除了它是一个用户)。

    【讨论】:

      【解决方案3】:

      您可以使用 HasColumnName(...) 否决默认列名

      public class UserConfiguration : EntityTypeConfiguration<User>
      {
          public UserConfiguration()
          {
               this.HasKey(t => t.Id);
      
               this.HasOptional(u => u.CreatedBy);
               // Map the 'DateCreated' Property to the 'CreatedById' table field.
               this.Property(u => u.DateCreated).HasColumnName("CreatedById");
      
               this.Property(u => u.Name).HasMaxLength(64);
               this.Property(u => u.Username).HasMaxLength(64);
           }
       }
      

      【讨论】:

      • 我为什么要将DateCreated 映射到CreatedById?这没有任何意义。 HasColumnName 仅适用于非导航属性。
      • 很抱歉。我的错。完全误读了您的问题。
      • 不用担心 :)。我也希望拥有HasColumnName,但是如果您像我的帖子中那样查看 MSDN,您会发现甚至无法控制导航属性名称。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-10
      • 1970-01-01
      • 1970-01-01
      • 2014-01-20
      • 2016-04-08
      相关资源
      最近更新 更多