Transient实例的NHibernate查询导致“保存瞬态实例”-exception

时间:2012-01-12 09:24:17

标签: nhibernate transient

我有一些旧代码执行查询,其中模型可能是瞬态的。也就是说,一个模型包含一些从用户输入填充的字段,然后将其用作查询的一部分。 它在NH 2.1.x下工作,但在最新版本下失败。

引发的异常是“对象引用未保存的瞬态实例 - 在刷新之前保存瞬态实例”。当NH尝试使用非持久对象作为查询的一部分执行查询时,会发生这种情况。

用于说明问题的简化版本。

abstract class BaseModel
   public virtual long Id { get; set; }

class Car : BaseModel
    public virtual Engine Engine { get;set; }

class Engine : BaseModel
    public virtual string Kind { get; set; }


public static IList<Car> GetByEngine(Engine eng) {
  ICriteria c = Session.CreateCriteria<Car>();
  c.Add(Expression.Eq("Engine", eng));
  return c.List<Car>(); // <--- Error occurs here
}

调用代码与此相同:

    Engine obj = new Engine { Id = 42 }; // Transient instance
    var x = GetByEngine(obj);

我期望发生的事情(这似乎是旧NHibernate版本的行为),是传递的引擎仅用于获取Id。也就是说,生成SQl之类的     从发动机= 42

的汽车中选择....

但是新版本的NHibernate似乎检查了Expression中使用的引擎是否真的存在。

有没有办法避免在执行查询之前加载持久化引擎?

3 个答案:

答案 0 :(得分:2)

是使用Session.Load()返回对象(如果已经在会话中)或lazyLoadingProxy(如果不存在)。

public static IList<Car> GetByEngine(Engine eng) {
    ICriteria c = Session.CreateCriteria<Car>();
    c.Add(Expression.Eq("Engine", Session.Load<Engine>(eng.Id)));
    return c.List<Car>();
}

答案 1 :(得分:1)

您可以使用Session.Load方法,该方法适用于此类情景 Load方法会向实体返回Proxy,并且不会访问数据库,直到您访问其中一个属性,(Primary key属性除外,它不会访问数据库在所有)。

用法:

Engine obj = session.Load<Engine>(42);
var x = GetByEngine(obj);

查看有关Session.GetSession.Load

this文章

答案 2 :(得分:0)

我认为你可以这样做:

public static IList<Car> GetByEngine(Engine eng) {
    ICriteria c = Session.CreateCriteria<Car>().CreateCriteria("Engine");
    c.Add(Expression.Eq("Id", eng.Id));
    return c.List<Car>();
}

无论如何......如果你还没有保存它,怎么可能有一台带引擎的汽车呢?