EF Code First с отношением «многие ко многим» со ссылками на самих себя

Я начинаю с использования EF Code First с MVC и немного озадачен чем-то. У меня есть следующая структура БД (извините, но, к сожалению, мне не разрешили опубликовать изображение):

Таблица – Товары
Таблица – Сопутствующие товары

1-много на Products.ProductID -> RelatedProducts.ProductID
1-много на Products.ProductID -> 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'."}

Что я делаю неправильно? В основном я хочу получить продукт, а затем выполнить итерацию по связанным продуктам и отобразить информацию об этом продукте.


person knappster    schedule 11.03.2011    source источник


Ответы (1)


Первая часть ответа заключается в том, что 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);
    }
person anon    schedule 18.03.2011
comment
Обратите внимание, что мы не можем каскадировать удаление отношения между Product.ProductID и RelatedProduct.RelatedProductID. Это не ограничение EF4: оно необходимо для предотвращения циклических каскадных удалений. - person anon; 18.03.2011
comment
Также обратите внимание, что отношения не являются симметричными. Если продукт1 добавлен как связанный с продуктом2, продукт2 не будет автоматически связан с продуктом1! - person anon; 18.03.2011
comment
Отлично, это сработало отлично, спасибо за это, пытался сделать это целую вечность! - person knappster; 24.03.2011
comment
Есть ли способ сделать это без использования Fluent API? то есть просто используя EF и DataAnnotations? - person Caltor; 31.10.2016