9

我开始与MVC使用EF代码优先和有点难以置信的东西。我有以下数据库结构(很抱歉,但我不允许张贴遗憾的是图像):EF代码首先与多对多的自我引用关系

表 - 产品
表 - RelatedProducts

上Products.ProductID

1-多 - > RelatedProducts.ProductID
1-Many on Products.ProductID - > RelatedProducts.RelatedProductID

基本上我有一个产品,可以有一系列与它相关的产品。这些保存在RelatedProducts表中,其关系由ProductID和我命名为RelatedProductID的相关产品的ProductID定义。在我的代码产生了以下类:

public class MyDBEntities : DbContext 
{ 
    public DbSet<Product> Products { get; set; } 
    public DbSet<RelatedProduct> RelatedProducts { get; set; } 
} 

public class Product 
{ 
    public Guid ProductID { get; set; } 
    public string Name { get; set; } 
    public string Heading { get; set; } 
    public string Description { get; set; } 
    public decimal Price { get; set; } 
    public Guid CategoryID { get; set; } 
    public string ImageURL { get; set; } 
    public string LargeImageURL { get; set; } 
    public string Serves { get; set; } 
    public virtual List<RelatedProduct> RelatedProducts { get; set; } 
} 
public class RelatedProduct 
{ 
    public Guid ProductID { get; set; } 
    public Guid RelatedProductID { get; set; } 
    public virtual Product Product { get; set; } 
    public virtual Product SimilarProduct { get; set; } 
} 

然后我尝试使用访问这些代码:

myDB.Products.Include("RelatedProducts").Where(x => x.ProductID == productID).FirstOrDefault(); 

但我不断收到以下错误:

{"Invalid column name 'ProductProductID2'.\r\nInvalid column name 'ProductProductID2'.\r\nInvalid column name 'ProductProductID'.\r\nInvalid column name 'ProductProductID1'.\r\nInvalid column name 'ProductProductID2'."} 

什么我做错了吗?我基本上想要获得产品,然后遍历相关产品并显示该产品信息。

回答

9

答案的第一部分是EF4 CTP5没有正确地将您的POCO映射到数据库,因为它不够智能。如果您查看数据库,您会得到:

CREATE TABLE RelatedProducts(
     RelatedProductID uniqueidentifier NOT NULL, 
     ProductID uniqueidentifier NOT NULL, 
     ProductProductID uniqueidentifier NULL, 
     ProductProductID1 uniqueidentifier NULL, 
     ProductProductID2 uniqueidentifier NULL, 
     PRIMARY KEY CLUSTERED 
     (
      RelatedProductID ASC 
     ) 
    ) ON [PRIMARY] 

Yuck!这需要通过一些手动工作来解决。在您的DbContext中,您添加如下规则:

protected override void OnModelCreating(ModelBuilder modelBuilder) 
    { 
     modelBuilder.Entity<Product>() 
      .Property(p => p.ProductID) 
      .HasDatabaseGenerationOption(DatabaseGenerationOption.Identity); 

     modelBuilder.Entity<RelatedProduct>() 
      .HasKey(rp => new { rp.ProductID, rp.RelatedProductID }); 

     modelBuilder.Entity<Product>() 
      .HasMany(p => p.RelatedProducts) 
      .WithRequired(rp => rp.Product) 
      .HasForeignKey(rp => rp.ProductID) 
      .WillCascadeOnDelete(); 

     modelBuilder.Entity<RelatedProduct>() 
      .HasRequired(rp => rp.SimilarProduct) 
      .WithMany() 
      .HasForeignKey(rp=> rp.RelatedProductID) 
      .WillCascadeOnDelete(false); 

     base.OnModelCreating(modelBuilder); 
    } 
+0

请注意,我们无法级联Product.ProductID和RelatedProduct.RelatedProductID之间的关系的删除。这不是EF4的限制:需要防止循环级联删除。 – anon

+0

另请注意,关系不对称。如果将product1添加为与product2相关,则product2不会自动关联到product1! – anon

+0

非常好,完美的工作,谢谢你,一直试图做这个很长的一段时间! – knappster