使用派生类型获取完整对象及其子集合

时间:2016-04-11 18:07:10

标签: c# entity-framework wcf nhibernate orm

我在C#ORM库中常见的惰性,急切和显式加载设计模式方面遇到了问题,特别是对于拥有自己的集合的派生类型。

例如,我想坚持下面的模型:

public abstract class Offer
{
    public int Id { get; set; }
}

public class DiscountOffer : Offer
{
    public float Percent { get; set; }
}

public class ColourOffer : Offer
{
    public List<string> Colours { get; set; }
}

public class Product
{
    public int Id { get; set; }
    public string Name { get; set; } = "Unknown";
    public IList<Offer> Offers { get; set; } = new List<Offer>();
}

我可以使用Entity Framework或NHibernate轻松映射并将其保存到数据库中,当我想要从数据库中检索完整产品并使用WCF通过线路发送时,就会出现问题。

如果我有以下产品:

new Product
{
    Name = "Chair",
    Offers = new List<Offer>
    {
        new DiscountOffer { Percent = 0.2f },
        new ColourOffer
        {
            Colours = new List<string>
            {
                "Red", "Blue", "Green"
            }
        },
    }
};

如果产品是延迟加载的,那么它将封装在代理中,以便它知道何时获取子集合。这会出现问题,因为序列化将失败,因为类型不符合预期。

我找到了一些问题的答案:

  1. 禁用延迟加载和急切/显式加载。这一直有效,直到您遇到抽象集合。我可以找到Include / Fetch ColourOffer.Colours路径的方法:
  2. NHibernate的:

    session.Get<Product>(1).Fetch(p => p.Offers) // If ColourOffer Fetch Colours?
    

    EF:

    DbSet<Product> Products { get; set; }
    
    // ...
    
    Products.Include(p => p.Offers) // If ColourOffer Include Colours?
    
    1. 使用DTO和AutoMapper。我已经收集了这个通常是一个好主意,但我遇到了同样的问题,不知道如何处理代理类,所以我必须禁用延迟加载,这让我回到第1点。

    2. 使用IDataContractSurrogate在序列化中加载内容。我尝试了几种在网络上浮动的实现,但我无法工作。我相信这是因为会话被序列化关闭了,因此无法获取集合的数据。

    3. 我现在不知道该怎么办。我只想加载一个完整的产品,但我找不到解决方案,这让我疯了。

1 个答案:

答案 0 :(得分:0)

使用Fluent NHibernate,添加DefaultLazy.Never()约定似乎会导致在请求时获取完整的对象图。

Fluently.Configure()
    // ...
    .Mappings(m => m
        .FluentMappings.AddFromAssemblyOf<MyClass>()
        .Conventions.Add(FluentNHibernate.Conventions.Helpers.DefaultLazy.Never()))
    // ...

这也有额外的好处,我没有必要处理不使用WCF的代理。