在内存集合和EntityFramework之间加入
是否有任何机制可以在保留顺序的同时在内存中集合和entity framework之间进行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实体。 结果集必须与内存中集合的顺序相同。
否,您无法在不将整个结果集加载到内存并使用linq-to-objects执行连接的情况下,无法使用数据库结果集加入内存中集合。 尝试使用contains而不是join:
var myNumbers = myInMemoryList.Select(i => i.RECORD_NUMBER); var itemsToAdd = efRepo.Where(e => myNumbers.Contains(e.RECORD_NUMBER));
这将使用IN
运算符生成查询
您可以在我的博客文章中阅读如何使用LINQKit或存储过程中的PredicateBuilder执行此操作。
http://kalcik.net/2014/01/05/joining-data-in-memory-with-data-in-database-table/
试试这个:
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
, Guid
等)时
加载整个efRepo怎么样? 我的意思是这样的(ToArray()):
var itemsToAdd = myInMemoryList.Join( efRepo.ToArray(), listitem => listitem.RECORD_NUMBER, efRepoItem => efRepoItem.RECORD_NUMBER, (left, right) => right);