このLINQクエリでコンパイル時間エラーが発生するのはなぜですか?

StackOverflow https://stackoverflow.com/questions/20354027

  •  25-08-2022
  •  | 
  •  

質問

以下のコードをコンパイルするときにコンパイル時間エラーが発生していますが、その理由がわかりません。

関係は多くの関係にあります

 var contacts = groups_to_querry
                .SelectMany(x => x.Contacts)
                .Where(x => x.ID == Guid.Empty)
                .SelectMany(p => p.ContactDetails)
                .Where(x => x.ID == Guid.Empty)
                .SelectMany(x => x.Contacts);  //This line gives me a compile time error 
                //Error : The Type argumetns for method 'System.Linq.Enumerable.SelectMany<TSource,Tresult>
                //(System.Collections.Generic.IEnumerable<TSource>, System.Func<TSource,
                //System.Collections.Generic.IEnumerable<TResult>>)' cannot be infrred from the usage.  
                //Try specifying the type arguments explicitly
役に立ちましたか?

解決

2回目は電話をかけます .SelectMany(x => x.Contacts), 、あなたは現在、コレクションで作業しています ContactDetails. 。あなたが使用できることは疑わしい SelectMany その上。使用する必要があります Select 代わりは。

SelectMany アイテムの複数のコレクションを選択し、それらを1つに入れたいときに使用されます IEnumerable. Select 個々のフィールドで使用されます。あなたはタイプのオブジェクトを使用しているので ContactDetail (これは1つしか連絡できないと思います)、あなたは使用する必要があります Select

編集:これがあなたが一言で言えば、段階的にやっていることです:

groups_to_querry.SelectMany(x => x.Contacts): :私がクエリしたいすべてのグループから、多くの連絡先をすべて選択します。各グループには多くの連絡先があるので、それらをすべて1つに入れます IEnumerable タイプのコレクション Contact

.Where(x => x.ID == Guid.Empty): :...しかし、空のIDを持つそれらの連絡先のみ

.SelectMany(p => p.ContactDetails): :次に、これらの連絡先のすべての連絡先を選択します。各連絡先には多くのcontactDetailsがあるので、それらをすべて1つに入れます IEnumerable タイプのコレクション ContactDetail

.Where(x => x.ID == Guid.Empty): :...しかし、空のIDを持つそれらのcontactDetailのみ

.SelectMany(x => x.Contacts);: :次に、ContactDetailsの各連絡先を選択します。ただし、コンパイラは、連絡先と接触デテールの間に1対多くの関係があることを知っているため、そのステートメントは不可能であるため、コンパイルエラーが表示されます。

他のヒント

意図したクエリを「連絡先の複数のグループから、ID = GUID.EMPTYを持つすべての連絡先を選択し、すべてがID = GUID.EMPTYを持っている詳細を選択します」と解釈しています。

コードが実際に解釈される方法は、「GUID.EMPTYを持つすべての連絡先から、GUID.EMPTYを持つすべての詳細を選択し、それらの詳細からすべての連絡先を選択します」です。最初の問題は、詳細から選択することになっていることです。これはファイナルを意味します SelectMany a Select, 、 なぜなら x.Contacts ここでは、詳細から連絡先までの多面的な関係を指します。

2番目の問題は、各詳細に同じ接点が含まれているため、結果に連絡先の複製が含まれることです。代わりにあなたがすべきことは、このような詳細コレクションに基づいて連絡先を直接フィルタリングすることです。

groups_to_query
.SelectMany(g => g.Contacts)
.Where(c => c.ID == Guid.Empty)
.Where(c => c.ContactDetails.All(d => d.ID == Guid.Empty))

また、これは詳細がゼロの連絡先を選択します。これはクエリとは異なる動作であるため、それがあなたが望むものかどうかはわかりません。別のフィルターを追加できます ContactDetails.Any() そうでない場合。

編集: エンティティフレームワークを使用しているため、上記はおそらく機能しません。サブクエリで詳細を選択し、実行後にメモリでフィルタリングする必要がある場合があります。

var queryResult =
    groups_to_query
    .SelectMany(g => g.Contacts)
    .Where(c => c.ID == Guid.Empty)
    .Select(c => new {
        contact = c,
        detailIDs = c.ContactDetails.Select(d => d.ID)
    }).ToList();

var contacts =
    queryResult
    .Where(r => r.detailIDs.All(id => id == Guid.Empty))
    .Select(r => r.contact);
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top