为什么这个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);



许可下: CC-BY-SA with attribution
不隶属于 Stack Overflow
这个KB合法吗? 是的,了解原因
许可下: CC-BY-SA with attribution
不隶属于 Stack Overflow
这个KB合法吗? 是的,了解原因