2012-01-12 10 views
1

モデルが一時的になる可能性のあるクエリを実行している古いコードがあります。つまり、ユーザー入力から取り込まれたいくつかのフィールドを持つモデルが、クエリの一部として使用されます。 NH 2.1.xで動作しましたが、最新バージョンでは失敗しています。TransientインスタンスによるNHibernateクエリの結果、 "一時インスタンスを保存する" - 例外

例外は「オブジェクトは未保存の一時インスタンスを参照しています - フラッシュする前に一時インスタンスを保存しています」。これはNHが、非永続オブジェクトをクエリの一部として使用してクエリを実行しようとしたときに発生します。

問題を説明する簡略化されたバージョン。

​​

とコードを呼び出すと、これに相当します:私は(古いNHibernateのバージョンの動作のように見えるもの)が起こることが予想何

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

、渡されたエンジンのみに使用されていることですイドを得るつまり、 select ....のようなSQlを生成しています。Cars where Engine = 42

しかし、新しいバージョンでは、NHibernateはExpressionで使用されているエンジンが実際に永続化されているかどうかをチェックしているようです。

クエリを実行する前に永続化されたエンジンを読み込まなくて済む方法はありますか?

答えて

2

はい、すでにセッションにある場合はオブジェクトを返し、存在しない場合はlazyLoadingProxyを返します。Session.Load()を使用します。

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>(); 
} 
+0

ご返信が遅れました。これはトリックを行い、OPで私の質問に答えます。手元にある問題を解決しました。 – Thomas

1

このようなシナリオでは、Session.Loadメソッドを使用できます。
Loadメソッドは、エンティティにProxyを返し、そのプロパティの1つにアクセスするまで(DBにまったく当たらないPrimary keyプロパティを除く)、データベースにヒットしません。

使用法:

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

チェックthis記事についてSession.GetSession.Load

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

をあなたはまだそれを保存していない場合、そのエンジンが存在する?

+0

実際のアプリケーションがここに投稿するにはあまりに複雑すぎるため、この例が考案されています。これは動作を再現した最小のシナリオでした。 – Thomas

関連する問題