【问题标题】:Influencing foreign key column naming in EF code first (CTP5)EF 代码优先影响外键列命名(CTP5)
【发布时间】:2011-02-22 19:36:52
【问题描述】:

我有一个 POCO 类,它与另一个类有两个单向一元关系,两个类共享一个祖先。生成的架构中的外键名称不反映属性名称。 (属性 MainContact 和 FinancialContact 给出 PersonId 和 PersonId1 字段名称)。

如何影响架构生成以生成与属性名称匹配的数据库列名称?

模型如下所示:

代码如下所示:

public class CustomerContext: DbContext
{
   public DbSet<Organisation> Organisations { get; set; }
   public DbSet<Person> Persons { get; set; }

   protected override void OnModelCreating(ModelBuilder builder)
   {
      DbDatabase.SetInitializer(new DropCreateDatabaseAlways<CustomerContext>());
   }
}

public abstract class Customer
{
   public int Id { get; set; }
   public string Name { get; set; }
}

public class Person : Customer
{
   public string Email { get; set; }
}

public class Organisation : Customer
{
   public Person FinancialContact { get; set; }
   public Person MainContact { get; set; }
}

架构如下所示:

druttka 的回答


druttka 在下面的回答完成了这项工作,很高兴知道这是一个 CTP5 错误。 EF 还需要指定级联行为,我按照 druttka 给出的链接中的示例使用 fluent API 来执行此操作。 Morteza Manavi here 的更多好读物。

现在的代码是这样的:

public class CustomerContext : DbContext
{
   public DbSet<Organisation> Organisations { get; set; }
   public DbSet<Person> Persons { get; set; }

   protected override void OnModelCreating(ModelBuilder builder)
   {
      DbDatabase.SetInitializer(new DropCreateDatabaseAlways<CustomerContext>());

      builder.Entity<Organisation>()
         .HasRequired(p => p.MainContact)
         .WithMany()
         .HasForeignKey(p => p.MainContactId)
         .WillCascadeOnDelete(false);
      builder.Entity<Organisation>()
         .Property(p => p.MainContactId)
         .HasColumnName("MainContact");

      builder.Entity<Organisation>()
         .HasRequired(p => p.FinancialContact)
         .WithMany()
         .HasForeignKey(p => p.FinancialContactId)
         .WillCascadeOnDelete(false);
      builder.Entity<Organisation>()
         .Property(p => p.FinancialContactId)
         .HasColumnName("FinancialContact");
   }
}

public abstract class Customer
{
   public int Id { get; set; }
   public string Name { get; set; }
}

public class Person : Customer
{
   public string Email { get; set; }
}

public class Organisation : Customer
{
   public Person FinancialContact { get; set; }
   public int FinancialContactId { get; set; }

   public Person MainContact { get; set; }
   public int MainContactId { get; set; }
}

现在提供了更合适的数据库:

【问题讨论】:

  • 使用属性来反映你的数据库模式命名不当?
  • 让我知道我的答案中的 EDIT 2 是否适合您。正如我所说,我测试了数据库是否按预期创建,但没有测试进一步的 CRUD 操作,所以我很想知道它是否正常运行。

标签: c# entity-framework code-first


【解决方案1】:

默认情况下,EF Code First 使用约定优于配置。但是,您可以通过覆盖 DbContent.OnModelCreating 来设置明确的替代方案。许多示例 here,由 ScottGu 提供。

编辑

所以在 CTP5 中,MapSingleType 如here 所述消失了。以下适用于简单的字符串属性,但不适用于您的组织与个人关系。我很好奇并计划继续研究它,但与此同时,也许这会让你开始,或者其他人可以完成答案。

public class Person : Customer
{
    [Column(Name="EmailAddress")]
    public string Email { get; set; }
}

编辑 2

好的,这就明白了。找到答案here。免责声明:我只验证了数据库模式是按预期创建的。我尚未测试播种数据或进一步的 CRUD 操作是否按预期工作。

public class Organisation : Customer
{
    [Column(Name = "FinancialContact")]
    public int? FinancialContactId { get; set; }
    [ForeignKey("FinancialContactId")]
    public Person FinancialContact { get; set; }
    [Column(Name = "MainContact")]
    public int? MainContactId { get; set; }
    [ForeignKey("MainContactId")]
    public Person MainContact { get; set; }
}

【讨论】:

  • 我会尝试实际试一试,并尽快发布一个明确的示例。
  • druttka - 感谢您的回复,这确实可以解决问题。我已经更新了答案以显示新代码。我还必须为每个组织属性添加一个反向属性,因为我需要指定级联行为,并且我使用了流畅的 API 版本而不是您使用的属性。非常感谢您对此的帮助:)
  • 更新 - 您不需要反向属性(这很好!)。在此处参考 Morteza Manavi 的帖子:weblogs.asp.net/manavi/archive/2011/01/23/…
猜你喜欢
  • 2018-02-13
  • 2018-05-31
  • 1970-01-01
  • 2013-07-29
  • 1970-01-01
  • 2014-02-14
  • 2016-01-31
  • 2014-03-28
相关资源
最近更新 更多