2016-07-06 11 views
0

単純なSELECTステートメントを実行する次のコードがあります。 "SQL Not Available"エラーが発生すると、このクエリは失敗します。 パターンと同じコードは、約20種類のモデルでうまく機能します。 実際には、SQLで実装されたビューのデザインを変更して、LoadID列を非表示にすると、クエリが失敗することがあります。実行可能... LoadIDが存在しないため。nHibernate SQLが利用できないエラー

このコード、のhbm.xmlモデル、およびビューのデザインはすべてses.Queryを(整列されている)は、これがマッピングされ、 "SQL利用できません"

var rows = ses.Query<vInventory>().Where(c => c.CustomerRecid == recid).Select(c => new vInventory() 
{ 
    InventoryRecid = c.InventoryRecid 
    , ItemID = c.ItemID 
    , LoadID = c.LoadID 
    , CustomerRecid = c.CustomerRecid 
}).ToList(); 

を記載した。

<?xml version="1.0" encoding="utf-8" ?> 
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" auto-import="true" assembly="Asmbly" namespace="Asmbly.Models"> 
    <class name ="vInventory" table="dbo.vInventory" dynamic-update="true"> 
    <cache usage="read-only"/> 
    <id name="InventoryRecid" column="InventoryRecid" type="Int64"> 
     <generator class="native" /> 
    </id> 
    <property name="ItemID" /> 
    <property name="LoadID" /> 
    <property name="CustomerRecid" /> 
    </class> 
</hibernate-mapping> 

更新に失敗しました。私はSQLビューの出力を取り出し、それをテーブルにダンプしました。 その後、テーブルを指すようにhbm.xlmを変更しました。 これでses.Query()が正常に動作します。これは実行可能な可能性ではありません。

InventoryRecidにコメントしてください。 SQLビューでは、この属性は

ROW_NUMBER() over (...)

は、どのように私はNHibernateは、このビューを使用してInventoryRecid属性を利用するために取得することができますか? 私はこのエンティティへの更新を試みることはありません。

更新#2: 私は

<class name ="vInventory" table="dbo.vInventory" dynamic-update="false"> 

再コンパイルし、私の問題がなくなっているに

<class name ="vInventory" table="dbo.vInventory" dynamic-update="true"> 

からhbm.xlmマッピングを変更しました。

残念ながら、私はそれをtrueに戻して再コンパイルして、問題は戻ってこない。

+0

あなたの意見を見せてください。 – epitka

+1

3つの異なるシステムを統合したCPEです。それは500行以上です。私はそれを効果的に行うことはできません。 – Steve

答えて

2

SelectメソッドでvInventoryの新しいインスタンスを作成する特別な理由はありますか? nHibernateはあなたのマッピングに基づいてこの型のオブジェクトを返すべきです。私はコンストラクタの呼び出しはSQLに変換することはできませんlinqプロバイダを台無しにするかもしれないと思う。 linqプロバイダは、通常の場合のようにSelectステートメントを処理しますIEnumerable

ここで何が起こるのですか: nHibernateは、これだけが.Where(c => c.CustomerRecid == recid)が実行される必要のあるクエリを取得します。したがって、nHibernateは、オブジェクトのIDの照会のみを行います(nHibernateが知っている限り、それ以上のプロパティは必要ありません)。 これはあなたに1, 2, 3, 4, 5, ...などを与えるでしょう。

Selectが実行されると(データベースではなく)nHibernateの数値が残りのプロパティが必要になると、IDで1つずつクエリを実行します(多くの結果であまり効率的ではありません)。現在、IDとしてROW_NUMBERを使用すると、現在の結果セットのみが考慮されるため危険です。単一のレコードを照会するとき、ROW_NUMBERは常に1になるので、nHibernateは残りのオブジェクトをもう見つけられません。

+0

興味深い。そして私は同意することができた。しかし、私はコンパイルエラーなしでその構文を書き換えることはできません。あなたはどのようにそれを書いていますか? – Steve

+0

'var rows = ses.Query ().Where(c => c.CustomerRecid == recid).ToList();'は、あなたが望む結果を得るのに十分です。しかし、それはあなたがあなたの視界を変えることができなければ十分ではありません。次に、このタイプの遅延読み込みを無効にする必要があります(nHibernateは常にすべてのプロパティを取得し、往復は必要ありません) – Pidon

+0

私が言ったように、私はhbm.xmlマッピングへの変更に取り組んでいます。しかし、私がそれを元に戻すと、それがなぜうまくいかないのか理解できません。しかし、私はあなたのvar行を実装すると....それはまだ私が欲しいものを行うようだ。これは、たぶん1ヵ月前に一度働いていたかもしれません。それからちょうど終わったようだ。理由は分かりません。しかし、冗長なSelect()を使わないでリストを作成する方が良いです。ありがとう。 – Steve

関連する問題