ADO EF Code Отображение первого общего промежуточного класса наследования - PullRequest
6 голосов
/ 25 апреля 2011

У меня есть следующее требование, которое хорошо работает в пространстве ОО, но я не могу заставить его отобразиться обратно на БД, используя сначала код ADO EF.

У меня есть множество продуктов, каждый из которых будет иметь разные аспекты (атрибуты, но не в смысле атрибутов кода). Например, кольцо будет иметь такие аспекты, как тип минерала = золото и т. Д., В то время как у алмаза будет аспект чистоты = VVSI1.

Как вы видите, продукты очень хорошо представлены в их составе, и мне нужен динамичный способ развития моей системы.

Как таковой, я создал класс продукта:

public class Product
{
    public int id { get; set; }
    public string Name { get; set; }
    private List<ProductAspect> aspects = new List<ProductAspect>();
    public List<ProductAspect> Aspects { get { return aspects; } set { aspects = value; } }
}

У него есть список ProductAspect, который является базовым классом для всех аспектов, движущихся вперед:

public class ProductAspect 
{
    public int id { get; set; }
    public string AspectName { get; set; }
}

Затем я наследую от ProductAspect, используя обобщенный тип, который позволяет мне быть точным (строго типизированным) относительно моего значения аспекта:

public abstract class ProductAspect<T> : ProductAspect
{
    public T AspectValue { get; set; }
}

Затем я создаю некоторые аспекты, которые позволят мне украсить свой продукт:

public class StringAspect : ProductAspect<string> { };
public class DecimalAspect : ProductAspect<decimal> { };
public class ImageAspect : ProductAspect<byte[]> { };

Затем я пробую DbContext и попробовал сопоставления наследования TPH и TPC.

Кажется, ни один из них не работает. Сгенерированная полученная модель БД не создает внешний ключ для таблиц StringAspect или DecimalAspect из таблицы аспектов.

public class IxamDataContext : DbContext
{
    public DbSet<Product> Products { get; set; }
    public DbSet<ProductAspect> Aspects { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
        AspectMapping(modelBuilder);
    }

    private void AspectMapping(DbModelBuilder mb)
    {
        //TPH
        //mb.Entity<ProductAspect>()
        //    .Map<StringAspect>(m => m.Requires("type").HasValue("sa"))
        //    .Map<DecimalAspect>(m => m.Requires("type").HasValue("da"));

        //TPC
        //mb.Entity<StringAspect>().ToTable("StringAspect");
        //mb.Entity<DecimalAspect>().ToTable("DecimalAspect");
    }
}

В результате возникает следующее исключение для этого кода заполнения:

        Product p = new Product();
        p.Name = "Diamond";
        p.Aspects.Add(new StringAspect() { AspectName = "History", AspectValue = "Old and long" });
        p.Aspects.Add(new DecimalAspect() { AspectName = "Weight", AspectValue= 96.5M });


        context.Products.Add(p);
        context.SaveChanges();

Excpetion:

EntityType 'StringAspect' не существовать в EntitySet 'IxamDataContext.Aspects'. параметр название: сущность

Есть идеи из первого кода EF?

Ответы [ 2 ]

4 голосов
/ 25 апреля 2011

Платформа сущностей не поддерживает промежуточные не отображенные типы в иерархии наследования.Это означает, что у вас не может быть этого наследства: A (сопоставлено) -> B (не сопоставлено) -> C (сопоставлено).EF также не поддерживает отображение универсальных типов.Это означает, что вы должны удалить общий промежуточный класс из иерархии и переместить AspectValue в производные типы с правильным типом.

0 голосов
/ 01 февраля 2012

Возможно, уже поздно, но я бы предложил вам использовать атрибут ComplexType , который позволит вам расширять ваши типы по вашему желанию.

...