【发布时间】:2016-04-11 18:07:09
【问题描述】:
我在使用 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"
}
},
}
};
如果产品是延迟加载的,则将其封装在代理中,以便知道何时获取子集合。这会带来一个问题,因为类型不符合预期,序列化将失败。
我找到了这个问题的几个答案:
- 禁用延迟加载和急切/显式加载。这一直有效,直到您遇到抽象集合。我可以找到
Include/FetchColourOffer.Colours路径的方法:
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?
使用 DTO 和 AutoMapper。我已经收集到这通常是一个好主意,但我遇到了 AutoMapper 的相同问题,不知道如何处理代理类,因此我必须禁用延迟加载,这让我回到第 1 点。
使用
IDataContractSurrogate在序列化时加载内容。我尝试了一些在网络上流传的实现,但我无法得到任何工作。我相信这是因为会话在序列化点被关闭,因此无法获取集合的数据。
我现在不知道该怎么办。我只想加载一个完整的产品,但我找不到解决方案,这让我发疯了。
【问题讨论】:
-
你真的试过
Include()吗?你有什么问题吗? -
恐怕这是不可能的。要使其工作,您必须将所需的所有属性放在单个类中,并根据手动分配的鉴别器将其映射到 Dtos/Domain 对象。
-
可能最好的选择是解决方案2,问题的解决方案很少见stackoverflow.com/questions/11816732/…
标签: c# entity-framework wcf nhibernate orm