1

我的实体看起来像这样简化: baseobject 和 product 是抽象的

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

我尝试了什么?

  • 添加<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 声明其基本对象是Product而不是Product1。我完全错了还是应该这样?

更新3:

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

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

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

从来都不是真的……

如果我称之为

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

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

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:我可以再次缩小问题范围。当它是第一次加载对象时的会话时,它不会发生。但我不能保证对于每个可能的用例。

最好的问候, 期待

4

1 回答 1

0

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

代理是根据 NH 可用的信息生成的,而不涉及 DB(这是拥有代理的全部意义)。当您有对 a 的引用时Product,它可能是 aProduct1或 a Product2,然后 NH 会生成一个继承自Product( ProductProxy) 的代理。要知道代理是否实际上应该是Product1or 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 的非代理。

于 2012-08-27T07:58:32.857 回答