当前位置:  开发笔记 > 编程语言 > 正文

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

如何解决《在NHibernate中获取正确类型的代理》经验,为你挑选了2个好方法。

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

领域模型

假设我有两个并行的类层次结构:Animal,Dog,Cat和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代表Animal而不是Dog.

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

约束

我无法更改域模型,模型由另一个部门交给我,我试图让他们更改模型并失败.

实际模型比示例复杂得多,并且类之间有很多引用,出于性能原因,使用急切加载或向查询添加联接是不可能的.

我完全控制源代码,hbm映射和数据库模式,我可以任何方式更改它们(只要我不改变模型类之间的关系).

我有很多方法,例如示例中的方法,我不想修改所有方法.

谢谢,
Nir



1> Stefan Stein..:

关闭动物类的延迟加载是最容易的.你说它无论如何都在记忆中.




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


据我所知,它只适用于AnimalOwner实际是代理的情况.

要么

您可以在动物所有者上使用泛型来使引用成为具体类.

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();



2> Pasi Savolai..:

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

public Animal Self { get { return this; } }

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

推荐阅读
家具销售_903
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有