Csharp/C#教程:在NHibernate中获取正确类型的代理分享


在NHibernate中获取正确类型的代理

我在nhibernate中遇到了未初始化的代理问题

领域模型

假设我有两个并行的类层次结构:Animal,Dog,Cat和AnimalOwner,DogOwner,CatOwner,其中Dog和Cat都inheritance自Animal和DogOwner,CatOwner都inheritance自AnimalOwner。 AnimalOwner有一个名为OwnedAnimal的类型的引用。

以下是示例中的类:

public abstract class Animal { // some properties } public class Dog : Animal { // some more properties } public class Cat : Animal { // some more properties } public class AnimalOwner { public virtual Animal OwnedAnimal {get;set;} // more properties... } public class DogOwner : AnimalOwner { // even more properties } public class CatOwner : AnimalOwner { // even more properties } 

这些类具有正确的nhibernate映射,所有属性都是持久的,并且可以延迟加载的所有内容都是延迟加载的。

应用程序业务逻辑只允许您在DogOwner中设置Dog,在CatOwner中设置Cat。

问题

我有这样的代码:

 public void ProcessDogOwner(DogOwner owner) { Dog dog = (Dog)owner.OwnedAnimal; .... } 

这种方法可以通过许多不同的方法调用,在大多数情况下,狗已经在内存中,一切都很好,但很少狗已经在内存中了 – 在这种情况下,我得到一个nhibernate“未初始化的代理”但是投掷抛出一个例外,因为nhibernate代表Animal而不是Dog。

我知道这是nhibernate的工作方式,但我需要知道类型而不加载对象 – 或者更正确的是我需要未初始化的代理作为Cat或Dog的代理而不是Animal的代理。

约束

谢谢,
尼尔

最容易为动物类关闭延迟加载。 无论如何,你说它主要是在记忆中。

    

作为其变体,您也可以使用no-proxy ,请参阅此post :

  

据我所知,它仅在AnimalOwner实际上是代理时才有效。

要么

您可以在动物所有者上使用generics来使引用成为具体类。

 class AnimalOwner { virtual TAnimal OwnedAnimal {get;set;} } class CatOwner : AnimalOwner { } class DogOwner : AnimalOwner { } 

要么

您可以将DogOwnersCatOwners映射到单独的表中,并在映射中定义具体的动物类型。

         

要么

你在NHibernate中乱七八糟,正如本博客所提出的那样。 NH实际上能够返回代理背后的真实对象。 这里提出了一个更简单的实现:

  public static T CastEntity(this object entity) where T: class { var proxy = entity as INHibernateProxy; if (proxy != null) { return proxy.HibernateLazyInitializer.GetImplementation() as T; } else { return entity as T; } } 

可以像这样使用:

 Dog dog = dogOwner.OwnedAnimal.CastEntit(); 

我认为我们最近遇到了类似的问题,AFAIR解决方案是给’动物’一个自我 – “方法/属性”:

 public Animal Self { get { return this; } } 

然后可以将其转换为纠正“动物”。 发生的事情是你的原始对象引用了nhibernate代理对象(当它被懒惰加载时),它对通过Animal类公开的所有方法充当Animal(它将所有调用传递给加载的对象)。 然而,它不能像你的任何其他动物一样被铸造,因为它不是这些,它只模仿动物类。 但是,由AnimalProxy封装的类可以作为子类动物进行转换,因为它是正确类的真实实例,您只需要获取它的引用即可。

您可能想尝试此操作以查看代理类型(假设NH 2.0+):

 ((INHibernateProxy)proxy).HibernateLazyInitializer.PersistentClass 

但是这种铸造或“偷看”无论如何都是非常糟糕的做法……

如果我们一直在处理同样的问题,那么问题在于生成的代理是Animal的代理,而不是Dog的代理。

我们使用的解决方案是重新加载对象:

 Dog dog = this.CurrentSession.Load(owner.OwnedAnimal.AnimalID); 

这将返回到您的会话并使用正确的类型重新加载对象。

希望这可以帮助

如果使用Fluent NHibernate,则可以使用自动映射覆盖来仅关闭该属性的延迟加载:

 public class DogOwnerMapOverride : IAutoMappingOverride { public void Override( AutoMapping mapping ) { mapping.References( x => x.OwnedAnimal ).Not.LazyLoad(); } } 

您可以尝试将此方法放在基础实体上:

上述就是C#学习教程:在NHibernate中获取正确类型的代理分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!

 public virtual T As() where T : Entity { return this as T; } 

本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。

ctvol管理联系方式QQ:251552304

本文章地址:https://www.ctvol.com/cdevelopment/1002757.html

(0)
上一篇 2021年12月28日
下一篇 2021年12月28日

精彩推荐