没有代理的持久性只发生在继承和隐式多态映射的类中?

时间:2012-08-22 14:49:41

标签: c# inheritance nhibernate-mapping

我的实体看起来像这样简化: baseobject and product are abstract

我使用xml文件映射。我有一个表和每个类的xml文件,除了抽象的。由于我使用延迟加载,我有很多代理。奇怪的是当我调用Refresh(obj)时,其中一个它每次都有效,除非该对象是Product1Proxy或Product2Proxy类型。然后我得到一个“没有persister for ... Proxy”错误。

我尝试了什么?

  • <mapping assembly="Project.DomainModel"/>添加到App.config
  • 检查所有.hbm.xml文件是否都是嵌入资源(它们是)
  • 我的课程是公开的
  • 他们有一个公共默认构造函数

我的NHibernate版本是3.3。

我的最后一个想法是我应该为我的产品使用另一个映射,但为什么它可以与CustomerProxy(和其他人)一起使用呢?在我看来,Customer和BaseObject与Product和Product1具有相同的关系。

可能是继承映射吗?我还没有看到另一个问题吗?

更新:现在我尝试在对象上调用Refresh(obj)之前取消对它们的修改,但该方法仍然会返回Product1Proxy。然后我尝试myObject is INHibernateProxy,但总是评估为假。为什么NHibernate不能识别自己的代理?

update2:我刚注意到,类型为Product1Proxy的myObject声明其baseobject是 Product 而不是 Product1 。我完全错了还是应该这样呢?

UPDATE3:

session.Refresh((NHibernate.Proxy.INHibernateProxy)product);

例如,这会导致无效的强制转换异常(Product1Proxy无法强制转换为INHibernateProxy)。

if (kitProduct is NHibernate.Proxy.INHibernateProxy) {
...
}

永远不会是真的......

如果我称之为

IList kitProductTemplates = ProductManager.Instance.LoadProductTemplates(checkBoxShowHidden.Checked);

Product1的列表(返回真实的Product1,没有Proxies),但如果我使用foreach迭代该列表,则对象是Proxy。查询如下所示:

public IList LoadAllTemplates(bool showHidden)
{
    IList loadedObjects = (IList)new ArrayList();
    try
    {
        ISession session = HibernateSessionManager.Instance.GetSession();
        ICriteria crit = session.CreateCriteria(typeof(Product1));
        crit.Add(Restrictions.Eq("IsTemplate", true));
        crit.SetResultTransformer(new DistinctRootEntityResultTransformer());
        crit.AddOrder(Order.Asc("Name"));
        crit.SetFetchMode("PickingList", FetchMode.Join);
        crit.SetFetchMode("SOP", FetchMode.Join);

        if (!showHidden) {

            crit.Add(Restrictions.Eq("IsHidden", false));
        }
        loadedObjects = crit.List();
    }
    catch (Exception ex)
    {
        throw (ex);
    }
    return loadedObjects;
}

(我刚发现,否则我会早点补充)

update4:我可以再次缩小问题范围。当对象首次加载时,它不会发生。但我无法保证每个可能的用例。

最好的问候,Expecto

1 个答案:

答案 0 :(得分:0)

您应该有代理的抽象类的映射。

代理是根据可用于NH的信息生成的,而不会触及数据库(这是拥有代理的全部意义)。当您引用Product(可能是Product1Product2)时,NH会生成一个继承自ProductProductProxy)的代理。要知道代理实际上应该是Product1还是Product2,它必须触及数据库,这不是我们想要的。

要解决此问题:使用子类或连接子类映射Product并映射Product1Product2。避免引用BaseObject,以避免生成BaseObjectProxy

修改:如果您仍需要引用BaseObject,请使用<any>

编辑2 :请注意,您永远不知道是否从查询中获取代理,除非您处于事务的开头。每当为产品创建代理时,NH都会从返回相同产品的每个查询中继续返回此代理。即使查询不会返回代理。这是为了确保您始终为同一事物获得相同的实例。

示例:

在DB中,您拥有ID为1,2和3的Product1。

// NH creates a proxy.
var proxy = session.Load<Product>(1);

// NH returns all Product1 instances, including the proxy
var allProducts = session.CreateCriteria(typeof(Product1)).List();

allProducts包含ID为1的代理和ID为2和3的非代理。