在LINQ JOIN查询中使用两个不同的数据上下文

时间:2017-06-12 14:30:28

标签: c# asp.net-mvc linq

我经历了许多有关此问题的问题并试图找到解决方案,但没有运气。所以这是我的情况:

private IQueryable<tblB> MT;
var IDs = (from z in db1.tblA
           where z.TA == User.Identity.Name
           select z).ToArray();

MT = from s in db2.tblB
     join a in IDs on s.BP equals a.BP                                  
     select new tblB() { LastName = s.LastName}); 

return View(MT.ToPagedList(pageNumber, pageSize));

我在return语句中遇到异常 - $ exception {“无法创建类型为'tblA'的常量值。在此上下文中仅支持基本类型或枚举类型。”} System.NotSupportedException

当我调试ID数组时,我看到它有来自tblA的数据,但第二次查询带有连接似乎不起作用。我犯了什么错误。帮助!

2 个答案:

答案 0 :(得分:3)

您需要使用Contains来生成和IN sql子句:

首先,更改第一个查询以返回所需的原始数据:

var IDs = (from z in db1.tblA
           where z.TA == User.Identity.Name
           select z.BP).ToArray();

然后在第二个查询中使用该内存列表:

MT = from s in db2.tblB
     where IDs.Contains(s.BP)                                
     select new tblB() { LastName = s.LastName}); 

顺便说一下,这不是2个上下文操作。您正在将第一个上下文中的数据加载到内存中(请注意.ToArray()),然后使用这些内存中的数据来查询第二个上下文。

答案 1 :(得分:0)

因此,您希望tblB的所有元素具有属性BP等于BP中元素的至少一个IDs属性。

问题是ToList() IDs位于本地内存后,而db1.tblB位于数据库中。您必须将两个序列连接到同一平台,既可以将数据库带到数据库,也可以同时带到本地内存。更高效的是什么取决于序列的实际大小和结果

如果要在数据库端执行查询,请

使用包含。完整的ID列表将被传输到数据库,执行查询并将结果传输到本地存储器。

如果ID非常短且结果几乎不完整tblA

,请使用此方法
var result = db2.tblB
   .Where(elementOfTableB => IDs.Contains(elementOftableB);

无需创建新的tblB对象,显然您需要完整的tblB对象。

使用AsEnumerable ,如果您希望与tblB中的元素数量相比有很多ID。将ID传输到数据库所需的时间比将完整的tblB传输到本地存储器要多得多。

db2.TblB                              // take all tblBelements
    .AsEnumerable()                   // bring to local memory
    .join(IDs,                        // join with list IDs
       tblBElement => tblBElement.BP  // take from each tblBElement the BP
       idElement => idElement.BP      // take from each ID the BP
       (tblBElement, idElement) =>    // when they match take the two records
                                      // and get  what you want. 
       tblBElement);                  // in this case the complete tblBElement