3

統合検索機能で使用される次の LINQ コードがあります。

var searchObjects =
    from objectA in this.context.DB.objectAs
    join objectB in this.context.DB.objectBs on objectA equals objectB.objectA into objectAB
    from AB in objectAB.Where(o => o.Type == "BasicGroup").DefaultIfEmpty()
    select new { objectA, objectB = AB};

foreach (var searchWord in searchWords)
{
    var searchObjects =
        searchObjects.Where(p => p.objectA.Name.Contains(searchWord) ||
            (p.objectB != null &&
                (p.objectB.Name.Contains(searchWord) ||
                p.objectB.ID.contains(searchWord))));
}

目標は、objectA の Name フィールド、または関連する objectB の Name または ID フィールドで検索語を探すことです。問題は、searchObjects を列挙しようとすると、NullReferenceException が返されるだけで、それ以上の詳細がないことです。

クエリの最初の部分は、組み合わせオブジェクトの適切なリストを (フィルターなしで) 返すので、問題は左結合にあるとは思いませんか?

何が例外を引き起こしているのかわかりませんので、助けていただければ幸いです。

私も Telerik の OpenAccess ORM を使用していますが、それが問題を引き起こしているとは思いませんか?

編集:

これは、Telerik OpenAccess ORM の問題であることが判明しました。特定の条件下では、適切な SQL の生成をあきらめ、すべてをメモリに描画し、それを L2Objects として扱います (@Dead.Rabit で指摘されているように、null では失敗するはずです)。 . 少なくとも問題の一部と思われる条件は、.DefaultIfEmpty() の前にある .Where(o => o.Type == "BasicGroup") でした。OpenAccess の最新バージョン (2013 Q1 SPI だったと思います) に更新すると、その条件を equals ステートメントの一部として書き直すことができます。

on new { objectA.ID, Type = "BasicGroup" } equals new { ID = objectB.AID, Type = object.Type }

これは SP1 より前では不可能でした。この新しいクエリを使用すると、検索語の Where 句をクエリに組み込むことができ、SQL をメモリに描画するのではなく生成することができます。

4

2 に答える 2

2

AB は、DefaultIfEmpty()関数で作成したため null になる可能性がありObjectA.Nameますが、null になる可能性がある場合も同様です。Contains()2 番目のステートメントでは、エラーがスローされます。同様に、ObjectB が null でないときに ObjectB.ID または ObjectB.Name が null になる可能性がある場合、ObjectB != nullガード句は目的の効果をもたらしません。

オブジェクトの簡単な列挙を試して、問題が最初のクエリにあることを確認してください

foreach( var item in searchObjects )
    Console.WriteLine( item.Type );

繰り返しごとに searchObjects 変数を再定義すると、SO へのコード ダンプで何かが失われると思いますが、JIC に言及する価値があります。

最後に、OpenAccess ORM については使用したことがないのでよくわかりませんが、このクエリは、WHERE 句で特定の種類の条件をサポートしていない LINQ の Dynamics CRM 実装では失敗します (詳細には触れません)。それは無関係だからですが、このクエリでそれらすべてを壊しました:p)。サード パーティの LINQ 実装の落とし穴に関するドキュメントを参照することは間違いなく価値があります。

于 2013-05-13T10:33:49.693 に答える
1

100%確信はありませんが、匿名型ABの代わりに使用する必要があると思います。objectB

select new { objectA, AB }

それは左結合の結果だからです。

于 2013-05-13T10:11:00.420 に答える