Свободный NHibermate и полиморфизм и новичок! - PullRequest
1 голос
/ 04 июня 2010

Я беглый новичок nhibernate, и я изо всех сил пытаюсь отобразить иерархию полиморфных объектов. Я создал следующую модель, воссоздающую суть того, что я делаю в моем реальном приложении.

У меня есть ProductList и несколько специализированных продуктов;

public class MyProductList
{
    public virtual int Id { get; set; }
    public virtual string Name {get;set;}
    public virtual IList<Product> Products { get; set; }

    public MyProductList()
    {
        Products = new List<Product>();   
    }
}

public class Product
{
    public virtual int Id { get; set; }
    public virtual string ProductDescription {get;set;}
}

public class SizedProduct : Product
{
    public virtual decimal Size {get;set;}
}

public class BundleProduct : Product
{
    public virtual Product BundleItem1 {get;set;}
    public virtual Product BundleItem2 {get;set;}
}

Обратите внимание, что у меня есть специализированный тип продукта под названием BundleProduct, к которому прикреплены два продукта.

Я могу добавить любой из специализированных типов продуктов в MyProductList, а комплектный продукт также может состоять из любых специализированных типов продуктов.

Вот беглое отображение nhibernate, которое я использую;

public class MyListMap : ClassMap<MyList>
{
    public MyListMap()
    {
        Id(ml => ml.Id);
        Map(ml => ml.Name);
        HasManyToMany(ml => ml.Products).Cascade.All();
    }
}

public class ProductMap : ClassMap<Product>
{
    public ProductMap()
    {
        Id(prod => prod.Id);
        Map(prod => prod.ProductDescription);
    }
}

public class SizedProductMap : SubclassMap<SizedProduct>
{
    public SizedProductMap()
    {
        Map(sp => sp.Size);
    }
}

public class BundleProductMap : SubclassMap<BundleProduct>
{
    public BundleProductMap()
    {
        References(bp => bp.BundleItem1).Cascade.All();
        References(bp => bp.BundleItem2).Cascade.All();
    }
}

У меня не настроено обратное сопоставление, поэтому продукт не знает, к каким спискам он принадлежит или в какие пакеты входит.

Далее я добавляю некоторые продукты в свой список;

        MyList ml = new MyList() { Name = "Example" };

        ml.Products.Add(new Product() { ProductDescription = "PSU" });
        ml.Products.Add(new SizedProduct() { ProductDescription = "Extension Cable", Size = 2.0M });

        ml.Products.Add(new BundleProduct()
        {
            ProductDescription = "Fan & Cable",
            BundleItem1 = new Product() { ProductDescription = "Fan Power Cable" },
            BundleItem2 = new SizedProduct() { ProductDescription = "80mm Fan", Size = 80M }
        });

Когда я сохраняю свой список в базе данных и перезагружаю его, сам список содержит ожидаемые элементы, т.е. MyList[0] имеет тип Product, MyList[1] имеет тип SizedProduct и MyList[2] имеет тип BundleProduct - отлично!

Если я перейду к BundleProduct, я не смогу увидеть типы Продукта, прикрепленные к BundleItem1 или BundleItem2, вместо этого они всегда являются прокси к Product - в этом примере BundleItem2 должен быть SizedProduct.

Могу ли я что-нибудь сделать, чтобы восстановить это либо в моей модели, либо в отображении?

Заранее спасибо за помощь.

1 Ответ

1 голос
/ 05 июня 2010

В сущности, свойства BundleItem1 и BundleItem2 всегда будут иметь прокси-сервер Product, поскольку NH создает ваши прокси-серверы, не касаясь базы данных, поэтому он не знает, являются ли они продуктами или каким-либо производным типом. Но когда вы вызываете метод для ваших элементов пакета, NH должен ударить по БД и загрузить правильную запись, и вы получите полиморфное поведение.

Вы можете проверить это. Добавьте переопределение ToString к вашему SizedProduct:

public override string ToString()
{
   return "I'm a sized product!";
}

Затем загрузите ваш BundleProduct и сделайте следующее:

Debug.WriteLine(bp.BundleItem1.ToString());
Debug.WriteLine(bp.BundleItem2.ToString());

Вы должны обнаружить, что второй вызов выводит «Я - продукт определенного размера!», И это продемонстрирует, что у вас рабочий полиморфизм.

Предполагая, что все это работает, как я описал, пришло время заняться реальным вопросом: что именно вы хотите сделать? Может быть, вы могли бы предоставить код, который на самом деле не работает так, как вы хотели бы.

...