1

我知道很多人在EF 4.1上询问一对一关系,但我似乎无法找到此问题的答案。EF 4.1代码优先 - 使用非标准列名称映射一对一关系

我有这些POCO类:

public class Contact 
{ 
    public decimal nCont_id { get; set; } 

    public virtual WebsiteMembership WebsiteMembership { get; set; } 
    //a bunch of other properties 
} 

public class WebsiteMembership 
{ 
    public int WebsiteMembershipId { get; set; } 

    public virtual Contact Contact { get; set; } 
} 

网站会员的主键(WebsiteMembershipId)也是一个外键引用联系人的nCont_id。

我试图设置此使用流利的API:

protected override void OnModelCreating(DbModelBuilder modelBuilder) 
{ 
    //This is being done because of the unconventional column names I have to live with 
    modelBuilder.Conventions.Remove<NavigationPropertyNameForeignKeyDiscoveryConvention>(); 

    //bunch of other stuff 
    modelBuilder.Entity<Contact>().ToTable("contacts"); 
    modelBuilder.Entity<Contact>().HasKey(b => b.nCont_id); 
    modelBuilder.Entity<Contact>().HasOptional(b => b.WebsiteMembership).WithRequired(b => b.Contact).Map(b => b.MapKey("WebsiteMembershipId")); 

    modelBuilder.Entity<WebsiteMembership>().ToTable("WebsiteMembership"); 
    modelBuilder.Entity<WebsiteMembership>().HasKey(b => b.WebsiteMembershipId); 

} 

,但我得到当我尝试做一个例外:

var websiteMembership = context.WebsiteMemberships.Where(c => c.WebsiteMembershipId == 1645942).FirstOrDefault(); 

例外:

模式指定无效。错误:(263,6):错误0019:类型中的每个 属性名称必须是唯一的。物业名称 'WebsiteMembershipId'已被定义。

这是否意味着我无法在EF CodeFirst上将外键设置为相同的主键?或者我在这里做错了什么?如果主键与外键不是同一列,它会起作用吗?

建议非常感谢!

回答

3

我认为当你定义这个映射...

modelBuilder.Entity<Contact>() 
    .HasOptional(b => b.WebsiteMembership) 
    .WithRequired(b => b.Contact) 
    .Map(b => b.MapKey("WebsiteMembershipId")); 

...你隐含定义什么是主,什么是从属的关系。显然Contact是主要原因,因为WebsiteMembership属性集对于Contact是可选的,所以它可以在没有WebsiteMembership的情况下存储。另一方WebsiteMembership实体需要参考Contact,这意味着它取决于Contact

委托人(Contact)是具有主键的实体,依赖于具有外键的实体(WebsiteMembership)。因此,当您使用MapKey来设置外键列的名称WebsiteMembershipId时,您将为表WebsiteMembership定义一个列,而不是Contact。但WebsiteMembership已经有一个名为WebsiteMembershipId的属性。 (我相信这是EF抱怨说属性名'WebsiteMembershipId'已被定义为。)在一对多关系中,外键是ContactId作为单独的属性/列,您必须使用HasForeignKey而不是MapKey。但是在一对一的关系中,显然外键是同时的主键,所以你根本不需要定义外键。

短长话短说:只是删除MapKey

modelBuilder.Entity<Contact>() 
    .HasOptional(b => b.WebsiteMembership) 
    .WithRequired(b => b.Contact); 

(但现在我很好奇,如果你可以定义一个intdecimal属性之间的关系,或者如果你得到一个错误)

+0

优秀的解释!非常感谢你一切正常。我以前试过上面这段代码,但是因为我的字段是'int'而不是'decimal',EF正在寻找Contact_nCont_id字段。然后我使用了你的代码片段并制作了“decimal”属性,一切都很好用。 –