简体   繁体   English

停止延迟加载或跳过在NHibernate中加载属性? 代理无法通过WCF序列化

[英]Stop lazy loading or skip loading a property in NHibernate? Proxy cannot be serialized through WCF

Consider I have a parent, child relationship class and mapping. 考虑我有父,子关系类和映射。 I am using NHibernate to read the object from the database, and intended to use WCF to send the object across the wire. 我正在使用NHibernate从数据库中读取对象,并打算使用WCF通过线路发送对象。

Goal 目标

  • For reading the parent object, I want to selectively, at different execution path, decide when I would want to load the child object. 为了读取父对象,我想有选择地在不同的执行路径上决定何时加载子对象。 Because I don't want to read more than what I needed. 因为我不想阅读超过我需要的东西。
  • Those partially loaded object must be able to sent through WCF. 那些部分加载的对象必须能够通过WCF发送。 When I mean I don't load it, neither side will access such property. 当我的意思是我没有加载它,双方都不会访问这样的属性。

Problem 问题

  • When such partially loaded object is being sent through WCF, as those property is marked as [DataContract] , it cannot be serialized as the property is lazy load proxy instead of real known type. 当通过WCF发送这样的部分加载的对象时,由于这些属性被标记为[DataContract] ,它不能被序列化,因为属性是延迟加载代理而不是真正的已知类型。

What I want to archive, or solution that I can think of 我想要存档的内容,或者我能想到的解决方案

  • lazy=false or lazy=true doesn't work. lazy=falselazy=true不起作用。 Former will eagerly fetch all the relationships, latter will create a proxy. 前者将急切地获取所有关系,后者将创建一个代理。 But I want nothing instead - a null would be the best. 但我不想要任何东西 - null是最好的。
  • I don't need lazy load. 我不需要延迟加载。 I hope to get a null for those references that I don't want to fetch. 我希望为那些我不想获取的引用获取null A null, but not just a proxy. null,但不仅仅是代理。 This will makes WCF happy, and waste less time to have a lazy-load proxy constructed. 这将使WCF满意,并浪费更少的时间来构建延迟加载代理。
    Like could I have a null proxy factory? 我可以拥有一个null代理工厂吗?
    -OR- -要么-
  • Or making WCF ignoring those property that's a proxy instead of real. 或者让WCF忽略那些代理而不是真实的属性。 I tried the IDataContractSurrogate solution , but only parent is passed to GetObjectToSerialize , I never observe an proxy being passed through GetObjectToSerialize , leaving no chance to un-proxy it. 我尝试了IDataContractSurrogate解决方案 ,但只有父传递给GetObjectToSerialize ,我从未观察到代理通过GetObjectToSerialize传递,没有机会取消代理它。

Edit 编辑

After reading the comments, more surfing on the Internet... 阅读评论后,更多在网上冲浪......

It seems to me that DTO would shift major part of the computation to the server side. 在我看来,DTO会将计算的主要部分转移到服务器端。 But for the project I am working on, 50% of time the client is "smarter" than the server and the server is more like a data store with validation and verification. 但对于我正在开发的项目,50%的时间客户端比服务器更“智能”,服务器更像是一个带有验证和验证的数据存储。 Though I agree the server is not exactly dumb - I have to decide when to fetch the extra references already, and DTO will make this very explicit. 虽然我同意服务器不是很愚蠢 - 我必须决定何时获取额外的引用,而DTO将使这一点非常明确。

Maybe I should just take the pain. 也许我应该忍受痛苦。 I didn't know http://automapper.codeplex.com/ before, this motivates me a little more to take the pain. 之前我不知道http://automapper.codeplex.com/ ,这激励我多一点痛苦。

On the other hand, I found http://trentacular.com/2009/08/how-to-use-nhibernate-lazy-initializing-proxies-with-web-services-or-wcf/ , which seems to be working with IDataContractSurrogate.GetObjectToSerialize . 另一方面,我发现http://trentacular.com/2009/08/how-to-use-nhibernate-lazy-initializing-proxies-with-web-services-or-wcf/ ,这似乎与IDataContractSurrogate.GetObjectToSerialize

Was getting the same issue with WCF-Silverlight transferring of DTO/Entities. WCF-Silverlight转移DTO / Entities时遇到了同样的问题。 I use following code which works fine: 我使用以下代码工作正常:

Fluent NHibernate: 流利的NHibernate:

References(c => c.DataSource)
    .Column("DataSourceId")
    .Cascade.None()
    .Not.LazyLoad();
HasManyToMany(c => c.Categories)
    .Table("Categories")
    .ParentKeyColumn("ItemId")
    .ChildKeyColumn("CategoryId")
    .Not.LazyLoad()
    .Cascade.None()
    .Inverse();

XML: XML:

<many-to-one name="DataSource" column="DataSourceId" lazy="false" cascade="none" />

Hope this'll work for you! 希望这对你有用!

I have run into similar issues with performance, what I did instead was preload the information I want by using an explicit call to the DB using a DetachedCriteria . 我遇到了与性能类似的问题,我所做的是通过使用DetachedCriteria对DB进行显式调用来预加载我想要的信息。

So similar to what you are doing I would probably do something like this. 与你正在做的事情类似,我可能会做这样的事情。

public DetachedCriteria BuildMyCriteria()
{
    var criteria = DetachedCriteria.For<ParentClass>();
    criteria.CreateCriteria("this.ChildClass", "Child Class").SetFetchMode("this.ChildClass", FetchMode.Eager);
    criteria.Add(Restrictions.IsNotNull("ChildClass.Property");      

    return criteria;
}

Then from my facade, I would get those entities with the properties that do not have null attributes on the child property 然后从我的外观,我会得到那些具有属性的实体,这些属性在子属性上没有null属性

var myClasses = _repository.ExecuteDetachedCriteria<ParentClass>(BuildMyCriteria);

Then I would have all ParentClass entities that have a null property. 然后我将拥有所有具有null属性的ParentClass实体。

So instead of taking a hit by constantly asking the DB for info, I store it in memory so it is ready for me to use. 因此,不是通过不断询问数据库获取信息,而是将其存储在内存中,以便我可以使用它。

This is just an alternative solution to DTOs, good luck :) 这只是DTO的替代解决方案,祝你好运:)

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

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