為什麼這個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。當您引用“本地”值時,實體框架必須在需要創建SQL查詢時確定如何處理它們。它基本上無法應對內存中集合和數據庫表之間的連接。

可能有用的一件事是使用Contains代替。我不知道LinkedList<T>是否適用於此,但我相信List<T> ,至少在LINQ to SQL中:

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
許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow