このLINQ joinステートメントが機能しないのはなぜですか?

c# entity-framework join linq linq-to-entities

質問

私はこのLINQクエリを持っています:

    // types...
    LinkedList<WeightedItem> itemScores = new LinkedList<WeightedItem>();

    var result = from i in _ctx.Items
                 join s in itemScores on i.Id equals s._id
                 orderby s._score descending
                 select new ItemSearchResult(i, s._score);

    // this fails:
    return result.ToList();

これはこのエラーを生成しています:

型 'System.Collections.Generic.IEnumerable`1'の定数値を作成できません。
このコンテキストでは、プリミティブ型(「Int32、String、Guidなど」)のみがサポートされています。

[編集]これWeightedItemのコードです。

public class WeightedItem
{
    public int _id;
    public decimal? _score;

    public WeightedItem(int id, decimal? score)
    {
        _id = id;
        _score = score;
    }
}

間違ったことがわかりますか。コードは完全にコンパイルされ、_ctx.ItemsとitemScoresの両方に適切な値が含まれています。

受け入れられた回答

はい、うまくコンパイルできます - 問題は、それをSQLに変換できないことです。 "local"値を参照する場合、エンティティフレームワークはSQLクエリを作成する必要があるときにそれらをどう処理するかを考え出す必要があります。基本的に、インメモリコレクションとデータベーステーブルの間の結合には対処できません。

うまくいく可能性があることの1つは、代わりにContainsを使用することです。 LinkedList<T>がこれに対応するかどうかはわかりませんが、少なくともLINQ to SQLでは、 List<T>が機能すると思います。

List<int> requiredScoreIds = itemScores.Select(x => x._id).ToList();

var tmp = (from i in _ctx.Items
           where requiredScoreIds.Contains(i.Id)
           orderby s._score descending
           select i).AsEnumerable();

// Now do the join in memory to get the score
var result = from i in tmp
             join s in itemScores on i.Id equals s._id
             select new ItemSearchResult(i, s._score);

これで、インメモリクエリで結合が行われました。これはやや不要です。代わりに辞書を使うこともできます。

List<int> requiredScoreIds = itemScores.Select(x => x._id).ToList();

var tmp = (from i in _ctx.Items
           where requiredScoreIds.Contains(i.Id)
           orderby s._score descending
           select i).AsEnumerable();

// Create a map from score ID to actual score
Dictionary<int, decimal?> map = itemScores.ToDictionary(x => x._id,
                                                        x => x._score);

var result = tmp.Select(i => new ItemSearchResult(i, map[i.Id]));

人気のある回答

メモリ内のリストとクエリ可能なオブジェクトとの間で結合することはできません。あなたはこのようなことをする必要があります:

var criteria = itemScores.Select(x => x._id).ToList();
var result_tag = (from i in _ctx.Items
                 where criteria.Contains(i.ID)
                 select i).ToList();
var result = from i in result_tag
             join s in itemScores on i.ID equals s._id
             orderby s._score descending
             select new ItemSearchResult(i, s._score);


Related

ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ
ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ