2012-03-02 45 views
0

我是EF新手,刚开始一个新项目。我目前有一个型号为BrandManagers的主键和三个外键。我不明白我应该如何映射这些在DbContext在EF代码优先的同一对象上映射多个外键

public class BrandManager 
{ 
    public int BrandManagerId { get; set; } 

    [Required()] 
    public int PersonId { get; set; } 

    [Required()] 
    public int BrandId { get; set; } 

    [Required()] 
    public int CountryId { get; set; } 

    public virtual Person Person { get; set; } 
    public virtual Brand Brand { get; set; } 
    public virtual Country Country { get; set; } 
} 

我该如何映射这个?我已经尝试了下面,无济于事。

protected override void OnModelCreating(DbModelBuilder modelBuilder) 
{ 
    modelBuilder.Entity<Person>() 
     .HasRequired(x => x.Country); 

    modelBuilder.Entity<Brand>() 
     .HasMany(x => x.BrandManagers); 

    modelBuilder.Entity<BrandManager>() 
     .HasRequired(x => x.Person); 
    modelBuilder.Entity<BrandManager>() 
     .HasRequired(x => x.Brand); 
    modelBuilder.Entity<BrandManager>() 
     .HasRequired(x => x.Country); 

    base.OnModelCreating(modelBuilder); 
    modelBuilder.Conventions.Remove<PluralizingTableNameConvention>(); 
} 

我不断收到

表“人”引进国外KEY约束“FK_Person_Country_CountryId”可能会导致循环或多个级联路径。

我没有找到在ASP.NET网站上的介绍教程,这个具体问题的任何解决方案,也没有在这里SO关于这方面的任何问题,所以我开始觉得我误解EF的一些基本部分。

回答

2

我的回答是更具体要怎么你在EF Code First中映射外键。我正准备在第二部分关于多重级联路径的工作,当时宽恕的回答是正确的。所以,不要扔掉我的答案,这可能对您有所帮助,下面是一般如何在EF中映射外键的答案:)。在底部的级联删除上稍微有点儿。

您可以在模型构建器中使用数据注释而无需映射。但是,如果您不希望您的POCO对象用数据库注释标记,我也使用modelBuilder提供了解决方案。

另一个需要注意的是,只要你有Person参考,你不需要PersonId。在这种情况下,生成器会为您创建FK(并且您的POCO类不会拥有它不需要的Id)。不过,将Id用于延迟加载可能是更好的做法(我不确定这是否是您做这件事的原因)。

最后,如果遵循约定,则甚至不需要设置外键。因此,如果您的Country类具有Id的PK,那么当您使用CountryId创建Country参考时,EF将通过CountryId是国家参考的FK的命名来实现。(Source

数据注释:

public class BrandManager 
{ 
    public int BrandManagerId { get; set; } 

    [Required()] 
    public int PersonId { get; set; } 

    [Required()] 
    public int BrandId { get; set; } 

    [Required()] 
    public int CountryId { get; set; } 

    [ForeignKey("PersonId")] 
    public virtual Person Person { get; set; } 
    [ForeignKey("BrandId")] 
    public virtual Brand Brand { get; set; } 
    [ForeignKey("CountryId")] 
    public virtual Country Country { get; set; } 
} 

的DbContext:(同样,在这种情况下,你不应该需要在你的POCO类中的任何数据的注解,因为它们都被设置在模型构建器)

modelBuilder.Entity<BrandManager>() 
    .HasRequired(x => x.Person) 
    .WithMany(x=>x.People) 
    .HasForeignKey(x=>x.PersonId); 

至于具体的错误,您需要添加.WillCascadeOnDelete(false),正如宽恕指出的BrandManager-> Country。您可以删除Person-> Country,但删除BrandManager会更好,因为它最终会通过Person路径级联。

+0

事情现在有道理。谢谢你的回答。 – sshow 2012-03-05 09:56:37

1

您遇到的问题是SqlServer问题。对于外键关系和删除级联中的多条删除路径,它往往非常保守。

你从品牌经理和个人的关系到国家的关系。一对一国删除会产生两个路径品牌经理:

Country -> Person -> Brand Manager 
Country -> Brand Manager 

的解决方案是,以消除删除这些实体的一个级联:

// Remove the cascade for country->Brand Manager. 
// Let it cascade through Person instead 
modelBuilder.Entity<BrandManager>() 
    .HasRequired(x => x.Country) 
    .WillCascadeOnDelete(false);