在内存集合和实体框架之间加入

时间:2011-07-01 11:40:05

标签: c# entity-framework linq join linq-to-entities

是否存在在保留订单的同时在内存中集合和实体框架之间进行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实体与内存中集合。结果集必须与内存中集合的顺序相同。

4 个答案:

答案 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成员是基本类型时,例如intstring,{{1等等)

答案 3 :(得分:0)

加载整个efRepo怎么样?我的意思是这样的(ToArray()):

var itemsToAdd = myInMemoryList.Join(
    efRepo.ToArray(),
    listitem => listitem.RECORD_NUMBER, efRepoItem => efRepoItem.RECORD_NUMBER, (left, right) => right);