C# 为什么这个LINQ join语句不起作用?
我有一个LINQ查询:C# 为什么这个LINQ join语句不起作用?,c#,linq,entity-framework,join,linq-to-entities,C#,Linq,Entity Framework,Join,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 desc
// 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();
你能看出我做错了什么吗?代码编译得很好,_ctx.Items和itemScores都包含正确的值。是的,它会编译得很好-问题是它无法将其转换为SQL。当您引用本地值时,实体框架必须确定在需要创建SQL查询时如何处理它们。它基本上无法处理内存集合和数据库表之间的连接 可能有效的一件事是使用Contains。我不知道LinkedList是否适用于此,但我相信List适用,至少在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);
以防万一_ctx.Items表示的表不是一个大表,您不关心加载 将所有表存储在内存中,然后在内存中对其进行过滤,您只需交换表中项目的顺序即可 join语句,如以下代码段所示:
LinkedList<WeightedItem> itemScores = new LinkedList<WeightedItem>();
var result = from s in itemScores
join i in _ctx.Items on s._id equals i.Id
orderby s._score descending
select new ItemSearchResult(i, s._score);
return result.ToList();
在原始语句中调用了Queryable扩展方法:
IQueryable<TResult> Queryable.Join<TOuter, TInner, TKey, TResult>(
this IQueryable<TOuter> outer,
IEnumerable<TInner> inner,
Expression<Func<TOuter, TKey>> outerKeySelector,
Expression<Func<TInner, TKey>> innerKeySelector,
Expression<Func<TOuter, TInner, TResult>> resultSelector
)
IEnumerable<TResult> Enumerable.Join<TOuter, TInner, TKey, TResult>(
this IEnumerable<TOuter> outer,
IEnumerable<TInner> inner,
Func<TOuter, TKey> outerKeySelector,
Func<TInner, TKey> innerKeySelector,
Func<TOuter, TInner, TResult> resultSelector
)
在交换的方法中,调用可枚举扩展方法:
IQueryable<TResult> Queryable.Join<TOuter, TInner, TKey, TResult>(
this IQueryable<TOuter> outer,
IEnumerable<TInner> inner,
Expression<Func<TOuter, TKey>> outerKeySelector,
Expression<Func<TInner, TKey>> innerKeySelector,
Expression<Func<TOuter, TInner, TResult>> resultSelector
)
IEnumerable<TResult> Enumerable.Join<TOuter, TInner, TKey, TResult>(
this IEnumerable<TOuter> outer,
IEnumerable<TInner> inner,
Func<TOuter, TKey> outerKeySelector,
Func<TInner, TKey> innerKeySelector,
Func<TOuter, TInner, TResult> resultSelector
)
因此,在最后一条语句中,full _ctx.Items表被加载到内存中,然后被联接,
通过Linq到对象,到我不知道的关于LinkedList的itemScores列表,我用list尝试了它
我之所以添加这个答案,主要是因为有人可以按相反的顺序键入连接,并将其保留下来
在没有意识到数据库中将要发生什么的情况下工作
我不建议以这种方式加入,尽管它在任何时候都可以用于后台应用程序
涉及的表由很少的记录组成,并且应用程序不会出现相关的性能恶化。
毕竟,这个解决方案保持了代码的整洁。你能发布WeightedItem的代码吗。DOK,这意味着?啊,见鬼-Jon Skeet打败了我:Jon Skeet是StackOverflow的Chuck Norris,所以.AsEnumerable执行查询并将结果保存在内存中是有意义的?如果不是,代码的哪一部分会执行?@Mickel:AsEnumerable不会立即执行查询-但它会返回IEnumerable而不是IQueryable,因此查询的其余部分将使用Enumerable.xxx而不是Queryable.xxx完成。当该查询最终需要执行时,它将在数据库中执行第一部分,在内存中执行第二部分。