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




.net proxy (4)

我有一个在nhibernate中未初始化的代理的问题

领域模型

比方说,我有两个并行的类层次结构:动物,狗,猫和AnimalOwner,DogOwner,CatOwner,其中Dog和Cat都继承了Animal,DogOwner和CatOwner都继承了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生成一个代理动物,而不是狗。

我明白,这是如何nhibernate工作,但我需要知道的类型没有加载对象 - 或者更正确地说,我需要未初始化的代理是猫或狗的代理,而不是代理的动物。

约束

  • 我不能改变领域模型,模型是由另一个部门交给我的,我试图让他们改变模型,并失败。
  • 实际模型比示例复杂得多,类之间有许多引用,使用预先加载或向查询添加连接不是出于性能原因的问题。
  • 我完全控制了源代码,hbm映射和数据库模式,我可以根据需要更改它们(只要不改变模型类之间的关系)。
  • 我有很多像这个例子中的方法,我不想修改所有的方法。

谢谢,
尼尔


你可能想试试看这个代理类型(假设NH 2.0+):

((INHibernateProxy)proxy).HibernateLazyInitializer.PersistentClass

但是这种铸造或者“偷看”是非常糟糕的做法。


我想我们最近也有类似的问题,AFAIR的解决方案是给“动物”一个自我“方法/财产”:

public Animal Self { get { return this; } }

这可以被用来纠正“动物”。 会发生什么是你的原始对象有一个对nhibernate代理对象的引用(当它被延迟加载时),这个对象通过Animal类暴露的所有方法(它将所有的调用传递给被加载的对象)充当Animal。 但是它不能像其他任何动物一样铸造,因为它不属于这些动物,它只能模仿动物类。 然而,由AnimalProxy封装的类可以作为子类化的动物被铸造,因为它是一个正确的类的实例,你只需要得到它的参考。


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

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

你可以尝试把这个方法放在你的基本实体上:

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




proxy