简体   繁体   English

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

[英]JSON.NET and nHibernate, ignore lazy loaded objects when serializing

I have a database with Car Histories.我有一个包含汽车历史的数据库。 Each car history has multiple images associated with it.每辆汽车历史都有多个与之相关的图像。 I am using NHibernate 2.2 to set up the relationships and the CarHistory mapping contains a bag for the images:我正在使用 NHibernate 2.2 来设置关系,并且 CarHistory 映射包含一个用于图像的包:

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

I have an iPad app which communicates with the server using JSON.我有一个 iPad 应用程序,它使用 JSON 与服务器进行通信。 I want to load all of the car history items into a list on the iPad and I don't want to include the photos when loading the list because it slows down the data retrieval which is why I have made the Photos lazy.我想将所有汽车历史记录项目加载到 iPad 上的列表中,我不想在加载列表时包含照片,因为它会减慢数据检索速度,这就是我将照片设为懒惰的原因。

When I try and use JsonConvert.SerializeObject to serialize my list of Car Histories I get a lazy initialization exception which is because I have loaded my objects and closed the session already because I don't need the photos and the JsonSerializer is touching all of the properties on the object.当我尝试使用 JsonConvert.SerializeObject 来序列化我的汽车历史列表时,我得到一个延迟初始化异常,这是因为我已经加载了我的对象并关闭了会话,因为我不需要照片并且 JsonSerializer 正在触及所有对象上的属性。

I would like to return the Json data to the client without the photos but I cannot use the ignore JsonProperty on my object because I want to load this collection in other situations.我想在没有照片的情况下将 Json 数据返回给客户端,但我不能在我的对象上使用 ignore JsonProperty,因为我想在其他情况下加载这个集合。

I have tried this but it just does the same thing giving me the lazy initialization exception: http://www.royjacobs.org/2011/07/27/using-json-net-to-serialize-proxied-nhibernate-objects/我试过这个,但它只是做同样的事情给我懒惰的初始化异常: http : //www.royjacobs.org/2011/07/27/using-json-net-to-serialize-proxied-nhibernate-objects/

This is my CarHistory (CarDetail) class这是我的 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; }
}

So my question is how can I retrieve a list of CarHistories without the associated Photos in some circumstances and not others?所以我的问题是如何在某些情况下而不是在其他情况下检索没有关联照片的 CarHistory 列表?

For cases like this you often want to come up with a layer in-between your "connected" domain objects and the serialization format.对于这种情况,您通常希望在“连接的”域对象和序列化格式之间设置一个层。 I usually create a data transfer object, which is similar to the domain model object, but usually doesn't have direct associations and instead just has lists of IDs.我通常创建一个数据传输对象,它类似于域模型对象,但通常没有直接关联,而只有 ID 列表。 I then use Automapper to map between the data transfer object and the domain object.然后我使用Automapper在数据传输对象和域对象之间进行映射。

The default contract-serializer tries serializing everything, and when it hits a thing-not-yet-loaded, it does not recognize it and attempts to serialize it.默认的合约序列化器尝试序列化所有内容,当它遇到尚未加载的事物时,它无法识别它并尝试序列化它。 That in turn forces the proxy to attempt loading the data, which causes performance problems (1 + n + n^2 + .. queries) or simply straight away throws an exception (when session's already closed) - and that's what you have observed in the first place.这反过来迫使代理尝试加载数据,这会导致性能问题(1 + n + n^2 + .. 查询)或直接抛出异常(当会话已经关闭时) - 这就是你在第一名。

Using a custom the contract-resolver, you will be able to instruct the serializer to not serialize collections and properties that were not loaded.使用自定义的合同解析器,您将能够指示序列化程序不要序列化未加载的集合和属性。 Or throw your better an exception, or log it, whatever you want in your case.或者抛出一个更好的异常,或者记录它,无论你想要什么。

See similar problem: JSON.Net Serialization of NHibernate Proxies (NH 3.3.2.4000) - you can find there an example of a custom ContractResolver.查看类似问题: JSON.Net Serialization of NHibernate Proxies (NH 3.3.2.4000) - 您可以在那里找到自定义 ContractResolver 的示例。

It's not complete for your needs though, since your problem is different, so when writing your own ContractResolver, inside it you should filter properties-to-be-serialized by, for example:但是,它并不完全满足您的需求,因为您的问题是不同的,因此在编写自己的 ContractResolver 时,您应该在其中过滤要序列化的属性,例如:

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

which produces false when the property contains a collection or object-reference that was proxied and was not loaded yet.当属性包含一个被代理但尚未加载的集合或对象引用时,它会产生false

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM