一个上下文引用 LINQ 查询引发多个引用异常 - BUG?
Posted
技术标签:
【中文标题】一个上下文引用 LINQ 查询引发多个引用异常 - BUG?【英文标题】:One context reference LINQ query throws multiple references exception - BUG? 【发布时间】:2014-12-18 12:02:27 【问题描述】:我正在使用以下代码:
using(MainEntities mainContext = new MainEntities())
return (from member in mainContext.aspnet_Membership
where adminGroupUserIDs.Contains(member.UserId)
select new
FullName = member.FirstName + " " + member.LastName,
UserName = (from user in mainContext.aspnet_Users
where user.UserId == member.UserId
select user.UserName)
).ToList();
其中adminGroupUserIDs
是一个IQueryable<GUID>
,它由对MainEntities
的不同实例的查询形成。
使用此查询 LINQ 抱怨:
指定的 LINQ 表达式包含对与不同上下文关联的查询的引用。
有什么想法吗?
【问题讨论】:
我不确定后台发生了什么,但也许您需要创建另一个 MainEntities 实例以在内部表达式中使用 (from user in mainContext.aspnet_Users ...
) - 请参阅 ***.com/questions/7332920/…
@Pzyon:恰恰相反。如果他这样做了,那么他肯定会得到那个错误。
【参考方案1】:
我无法从您在此处显示的代码中确定,但我很确定 adminGroupUserIDs
是另一个尚未检索到的查询的结果,并且是使用 @987654322 的不同实例创建的@。您不能混合来自不同上下文的查询,甚至不能混合来自同一上下文类的不同实例。尝试将其更改为以下内容:
var loadedAdminGroupUserIDs = adminGroupUserID.ToArray();
using(MainEntities mainContext = new MainEntities())
return (from member in mainContext.aspnet_Membership
where loadedAdminGroupUserIDs.Contains(member.UserId)
select new
FullName = member.FirstName + " " + member.LastName,
UserName = (from user in mainContext.aspnet_Users
where user.UserId == member.UserId
select user.UserName)
).ToList();
【讨论】:
阿隆的优点。我完全忽略了adminGroupUserIDs
!最初,我发布的查询使用存储库模式方式的存储库构建查询,即使用MembershipRepository.All
和UsersRepository.All
。但后来我收到了上面发布的错误并切换到using
块。但我认为你成功了,因为 adminGroupUserIDs
是并且 IQueryable 是由第三个存储库构建的!
您修复的问题是loadeAdminGroupUserIDs
现在在内存中,我一定会收到Unable to create a constant value of type
错误,因为查询在数据库中。最后我不得不加入一个连接,这可能更接近原生 SQL。但我仍然确信我可以实施您的解决方案。我错过了什么?
另一点。我把自己绊倒了,因为我想从我的存储库构建我的查询,每个存储库都代表一个表。使用这种模式,每个 Repo 都会实例化一个 MainEntities
上下文。从这个案例中收集,我是否可以推断出 Repo 模式仅在仅对一个表执行查询时才有用?我是否错误地实施了该模式?这可能是另一个 SO 问题。
假设adminGroupUserIDs
是IQueryable<int>
(或<long>
),我上面的建议将导致实体框架将.Contains(...)
转换为IN
表达式,这样如果adminGroupUserIDs
包含三个 ID,5、18 和 42,这三个值的内存数组将由第一行创建,然后 EF 将识别这一点并创建以下 SQL:WHERE UserId IN (5, 18, 42)
,它也可以不使用单个数据上下文。但是,如果您希望所有这些都发生在数据库中,那么您必须使用单个数据上下文(有或没有连接)。
对不起,Allon,我错过了一个重点。 adminGroupUserIDs
是一个 GUID :(。这解释了为什么 .Contains
失败了。感谢您的洞察力。将编辑我的问题。【参考方案2】:
尝试将.FirstOrDefault()
添加到您的子查询中。
using(MainEntities mainContext = new MainEntities())
return (from member in mainContext.aspnet_Membership
where adminGroupUserIDs.Contains(member.UserId)
select new
FullName = member.FirstName + " " + member.LastName,
UserName = (from user in mainContext.aspnet_Users
where user.UserId == member.UserId
select user.UserName).FirstOrDefault()
).ToList();
【讨论】:
是的,这是查询中的另一个错误,很好!虽然我不明白它是如何导致上述错误的。 好收获。不幸的是,问题正是@AllonGuralnek 建议的,我包括了 3 个!我的查询中有不同的MainEntity
上下文(查询本身中有2 个,adminGroupUserIDs
是来自第三个MainEntities
上下文的IQueryable)。这就是使用存储库模式的现实。我需要 3 个不同的存储库,每个存储库都实例化了一个 MainEntities
上下文。以上是关于一个上下文引用 LINQ 查询引发多个引用异常 - BUG?的主要内容,如果未能解决你的问题,请参考以下文章
对 ITVF 的引用会引发“在前一个操作完成之前在此上下文上启动的第二个操作”异常
错误:“指定的 LINQ 表达式包含对与不同上下文关联的查询的引用”