是否存在在保留订单的同时在内存中集合和实体框架之间进行JOIN的机制。
我正在尝试的是
var itemsToAdd =
myInMemoryList.Join(efRepo.All(), listitem => listitem.RECORD_NUMBER,
efRepoItem => efRepoItem.RECORD_NUMBER, (left, right) => right);
这给了我一个相当奇怪的标题“这个方法支持LINQ to Entities基础结构,并不打算直接在你的代码中使用。”错误。
现在我当然可以用
之类的东西迭代地做到这一点 foreach (var item in myInMemoryList)
{
var ho = efRepo.Where(h => h.RECORD_NUMBER == item.RECORD_NUMBER).FirstOrDefault();
tmp.Add(ho);
}
但这是一个N + 1查询。哪个是讨厌的,因为myInMemoryList可能非常大!
Resharper可以为我重构
tmp = (from TypeOfItemInTheList item in myInMemoryList
select efRepo.Where(h => h.RECORD_NUMBER == item.RECORD_NUMBER)
.FirstOrDefault());
我怀疑仍在进行N + 1次查询。因此,有任何想法可以更好地获取与关键字段匹配的ef实体与内存中集合。结果集必须与内存中集合的顺序相同。
答案 0 :(得分:17)
否则,如果不将整个结果集加载到内存并使用linq-to-objects执行连接,则无法使用数据库结果集加入内存中集合。尝试使用contains而不是join:
var myNumbers = myInMemoryList.Select(i => i.RECORD_NUMBER);
var itemsToAdd = efRepo.Where(e => myNumbers.Contains(e.RECORD_NUMBER));
这将生成IN
运算符
答案 1 :(得分:3)
您可以在我的博客文章中了解如何使用LINQKit或存储过程中的PredicateBuilder执行此操作。
http://kalcik.net/2014/01/05/joining-data-in-memory-with-data-in-database-table/
答案 2 :(得分:2)
试试这个:
var list = (from n in efRepo
where myInMemoryList.Select(m=>m.RECORD_NUMBER).Contains(n.RECORD_NUMBER)
select n).ToList();
Contains
将被转换为SQL中的IN
运算符(仅当您的RECORD_NUMBER
成员是基本类型时,例如int
,string
,{{1等等)
答案 3 :(得分:0)
加载整个efRepo怎么样?我的意思是这样的(ToArray()):
var itemsToAdd = myInMemoryList.Join(
efRepo.ToArray(),
listitem => listitem.RECORD_NUMBER, efRepoItem => efRepoItem.RECORD_NUMBER, (left, right) => right);