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 版本的行为)是传递的 Engine 仅用于获取 Id。也就是说,生成SQl就像 select .... from Cars where Engine = 42
但在新版本中,NHibernate 似乎会检查表达式中使用的引擎实际上是否持久存在。
有没有办法避免在执行查询之前加载持久引擎?
I have some old code which is performing a query where a model can be transient. That is, a model with some fields populated from user input, which are then used as part of the query.
It worked under NH 2.1.x, but is failing under the latest version.
The exception raised is "object references an unsaved transient instance - save the transient instance before flushing". This happens when NH attempts to perform a query using a non-persisted object as part of the query.
A simplified version to illustrate the problem.
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
}
And calling code is equivalent to this:
Engine obj = new Engine { Id = 42 }; // Transient instance
var x = GetByEngine(obj);
What I expected to happen (Which appears to be the behaviour of the old NHibernate version), is that the Engine passed is used only for getting the Id. That is, generating SQl like
select .... from Cars where Engine = 42
But with the new version NHibernate seems to check that the engine used in the Expression is actually persisted.
Is there a way to avoid having to load a persisted Engine before performing the query ?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
是的,使用 Session.Load() ,如果已经在会话中,则返回对象,如果不存在,则返回lazyLoadingProxy。
yes using
Session.Load()
which returns the object if already in the session or a lazyLoadingProxy if not present.您可以使用针对此类场景的
Session.Load
方法。Load
方法将向实体返回一个Proxy
,并且在您访问其属性之一之前不会访问数据库(主键
除外) code> 属性根本不会影响数据库)。用法:
检查这个 关于
Session.Get
和Session.Load
的文章You can use the
Session.Load
method, which exist for this kind of scenarios.The
Load
method will return aProxy
to the Entity and won't hit the Data Base untill you access one of it's properties, (except thePrimary key
property which won't hit the DB at all).Usage:
check this article about
Session.Get
andSession.Load
我认为你可以做这样的事情:
无论如何......如果你还没有保存带有该引擎的汽车怎么可能存在?
I think you could do something like this:
Anyway... how it's possible that a car with that engine exists if you haven't saved it yet?