影响EF代码中的外键列命名(CTP5) [英] Influencing foreign key column naming in EF code first (CTP5)

查看:168
本文介绍了影响EF代码中的外键列命名(CTP5)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



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



模型看起来像这样:





代码如下所示:

 code> public class CustomerContext:DbContext 
{
public DbSet< Organization>组织{get;组; }
public DbSet< Person>人{get;组;

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

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

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

public class组织:Customer
{
public Person FinancialContact {get;组; }
public Person MainContact {get;组; }
}

架构如下所示:



druttka的回答






druttka在下面的答案做了这个工作,很高兴知道这是一个CTP5错误。 EF还需要指定级联行为,并且使用流畅的API按照druttka提供的链接中的示例执行此操作。来自Morteza Manavi的一些更好的阅读,由ScottGu提供。



编辑



所以在CTP5中,MapSingleType如下所述:这里。以下内容适用于简单的字符串属性,但不适用于您的Organization to Person关系。我很好奇,并计划继续关注它,但在此期间,也许这将使您的开始或其他人可以完成答案。

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

编辑2



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

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


I have a POCO class that has two one-way unary relationships with another class, both classes share an ancestor. The names of the foreign keys in the generated schema do not reflect the property names. (Properties MainContact and FinancialContact give PersonId and PersonId1 field names).

How can I influence schema generation to generate database column names that match the property names?

The model looks like this:

The code looks like this:

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; }
}

The schema looks like this:

Answer from druttka


druttka's answer below did the job and it's nice to know that it's a CTP5 bug that's behind this. EF also needs the cascade behaviour to be specified and I've used the fluent API to do this following the example in the link given by druttka. Some more good reading from Morteza Manavi here.

The code now is this:

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; }
}

Which now gives the far more suitable database:

解决方案

EF Code First uses, by default, convention over configuration. However, you can set explicit alternatives by overriding DbContent.OnModelCreating. Many examples here, courtesy of ScottGu.

EDIT

So in CTP5, MapSingleType went away as described here. The following works for simple string properties, but not for your Organisation to Person relationships. I'm curious and plan to keep looking at it, but in the meantime, maybe this will get your started or someone else can complete the answer.

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

EDIT 2

Ok, this gets it. Found the answer here. Disclaimer: I've only verified that the database schema is created as expected. I have not tested that seeding data or further CRUD operations work as expected.

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; }
}

这篇关于影响EF代码中的外键列命名(CTP5)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆