我经历了许多有关此问题的问题并试图找到解决方案,但没有运气。所以这是我的情况:
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的数据,但第二次查询带有连接似乎不起作用。我犯了什么错误。帮助!
答案 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