0

以下のスキーマを前提として、必要なフォームが欠落している連絡先を返すEFクエリを作成しようとしています。各連絡先には、FormTypesのコレクションに関連するContactTypeがあります。すべての連絡先は、そのContactTypeに関連するFormTypesの少なくとも1つのフォーム(ContactForm内)を持っている必要があります。

以下のlinqクエリからEFが生成するクエリは、SQL Serverに対しては機能しますが、Oracleに対しては機能しません。

var query = ctx.Contacts.Where (c => c.ContactType.FormTypes.Select (ft => ft.FormTypeID)
                            .Except(c => c.Forms.Select(f => f.FormTypeID)).Any());

SQL Serverに対して機能するすべてのEFクエリが、DevartのdotConnectデータプロバイダーを使用してOracleに対しても機能するように、データレイヤーをリファクタリングしているところです。

OracleがスローしているエラーはORA-00904:"Extent1"。"ContactID":無効な識別子です。

問題は、Oracleがレベル2以降のネストされたサブクエリのクエリからのテーブル列の参照をサポートしていないことです。Oracleがスローする行は、「Extent1」。「ContactID」を参照しているExcept(またはマイナス)サブクエリにあります。「Extent1」は、クエリの最上位で定義されている連絡先のエイリアスです。これは、Oracleの制限に関するDevartの説明です

多くのクエリでこの問題を解決する方法は、SelectMany()と場合によってはJoin()を使用して、テーブル間の関係をWhere()述語からクエリの本体に移動するように書き直すことです。これにより、データベースサーバーに送信されるクエリがフラットになり、EFによって生成されるサブクエリが最小化または排除される傾向があります。 これは、左外部結合を使用して解決された同様の問題です。

列"Extent1"。"ContactID"が存在し、EFとDevartが生成するクエリの命名構文は問題ではありません。

このクエリを書き直す方法についてのアイデアは大歓迎です。目的は、OracleおよびSQLServerに対して機能する連絡先のContactTypeに必要なFormTypeのフォームが欠落している連絡先を返すクエリです。

ここに画像の説明を入力してください

4

1 に答える 1

1

次のエンティティフレームワーククエリは、SQL ServerとOracleの両方に対してクエリを実行するときに、ContactTypeに必要なFormTypeが欠落している連絡先のすべてのContactIDを返します。

var contactNeedsFormTypes = 
       from c in Contacts 
       from ft in c.ContactType.FormTypes
       select new { ft.FormTypeID, c.ContactID};

var contactHasFormTypes = 
       from c in Contacts
       from f in c.Forms
       select new { c.ContactID, f.FormTypeID};

var contactsMissingFormTypes = 
       from n in contactNeedsFormTypes
       join h in contactHasFormTypes
          on new {n.ContactID, n.FormTypeID} equals new {h.ContactID, h.FormTypeID}
              into jointable
              where jointable.Count()==0
select n.ContactID;

contactsMissingFormTypes.Distinct();
于 2013-01-03T21:23:48.927 に答える