JSON.NET和nHibernate,在序列化时忽略延迟加载的对象

时间:2012-09-25 05:10:12

标签: c# nhibernate json.net

我有一个Car Histories数据库。每个汽车历史记录都有多个与之相关的图像。我使用NHibernate 2.2建立关系,CarHistory映射包含图像包:

<bag name="Photos" table="DetailPhoto" cascade="all" lazy="true">
  <key column="CAR_DETAIL_ID"/>
  <one-to-many class="DetailPhoto"/>
</bag>

我有一个使用JSON与服务器通信的iPad应用程序。我想将所有汽车历史项目加载到iPad上的列表中,我不想在加载列表时包含照片,因为这会减慢数据检索速度,这就是我使照片变得懒惰的原因。

当我尝试使用JsonConvert.SerializeObject来序列化我的Car Histories列表时,我得到了一个懒惰的初始化异常,因为我已经加载了我的对象并关闭了会话因为我不需要照片并且JsonSerializer正在触摸对象上的所有属性。

我想在没有照片的情况下将Json数据返回给客户端但我不能在我的对象上使用ignore JsonProperty,因为我想在其他情况下加载此集合。

我试过这个但它只是做了同样的事情给了我懒惰的初始化异常: http://www.royjacobs.org/2011/07/27/using-json-net-to-serialize-proxied-nhibernate-objects/

这是我的CarHistory(CarDetail)课程

 public class CarDetail
{
    [JsonProperty("id")]
    public virtual int Id { get; set; }

    [JsonProperty("carId")]
    public virtual int CarId { get; set; }

    [JsonProperty("date")]
    public virtual DateTime ? Date { get; set; }

    [JsonProperty("details")]
    public virtual string Details { get; set; }

    [JsonProperty("photos")]
    public virtual IList<DetailPhoto> Photos { get; set; }
}

所以我的问题是如何在某些情况下检索没有相关照片的CarHistories列表而不是其他情况?

2 个答案:

答案 0 :(得分:1)

对于这种情况,您需要在“连接”域对象和序列化格式之间创建一个图层。我通常创建一个数据传输对象,它类似于域模型对象,但通常没有直接关联,而只是有ID列表。然后我使用Automapper在数据传输对象和域对象之间进行映射。

答案 1 :(得分:0)

默认的contract-serializer尝试序列化所有内容,当它遇到尚未加载的东西时,它无法识别它并尝试序列化它。这反过来迫使代理尝试加载数据,这会导致性能问题(1 + n + n ^ 2 + ..查询)或者直接抛出异常(当会话已经关闭时) - 这就是你在第一名。

使用自定义合约解析程序,您将能够指示序列化程序不序列化未加载的集合和属性。或者抛出更好的异常,或者记录它,无论你想要什么。

查看类似问题:JSON.Net Serialization of NHibernate Proxies (NH 3.3.2.4000) - 您可以找到自定义ContractResolver的示例。

虽然您的需求并不完整,因为您的问题不同,因此在编写自己的ContractResolver时,您应该在其中过滤要序列化的属性,例如:

var propertyInfo = (PropertyInfo)member;
var value = propertyInfo.GetValue(target);
var shouldSerialize = NH.NHibernateUtil.IsInitialized(value);

当属性包含已代理但尚未加载的集合或对象引用时,会生成false