EF Code First自引用多对多关系

9
我正在使用EF Code First with MVC,涉及到it技术,并且有点困惑。我有以下数据库结构(很抱歉,我不能发布图片):
表 - 产品 表 - 相关产品
在Products.ProductID上的1对多关系-> RelatedProducts.ProductID 在Products.ProductID上的1对多关系-> RelatedProducts.RelatedProductID
基本上,我有一个产品,它可以有一系列与之相关的产品。这些产品存储在RelatedProducts表中,关系由ProductID和相关产品的ProductID定义,我将其命名为RelatedProductID。在我的代码中,我已经生成了以下类:
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'."}

我做错了什么?我想获取一个产品,然后迭代相关产品并显示该产品的信息。
1个回答

10

首先,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]  

呃!这需要通过一些手动处理来修复。在你的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);
    }

请注意,我们不能在Product.ProductID和RelatedProduct.RelatedProductID之间的关系上进行级联删除。这不是EF4的限制:它是为了防止循环级联删除而需要的。 - anon
请注意,关系不是对称的。如果将product1添加为与product2相关联,则product2不会自动与product1相关联! - anon
太棒了,完美地解决了,非常感谢,我已经尝试做这件事很久了! - knappster
1
有没有一种不使用Fluent API的方法?也就是只使用EF和DataAnnotations? - Caltor

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接