【问题标题】:One context reference LINQ query throws multiple references exception - BUG?一个上下文引用 LINQ 查询引发多个引用异常 - 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 ...) - 请参阅 stackoverflow.com/questions/7332920/…
  • @Pzyon:恰恰相反。如果他这样做了,那么他肯定会得到那个错误。

标签: c# linq


【解决方案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.AllUsersRepository.All。但后来我收到了上面发布的错误并切换到using 块。但我认为你成功了,因为 adminGroupUserIDs 是并且 IQueryable 是由第三个存储库构建的!
  • 您修复的问题是loadeAdminGroupUserIDs 现在在内存中,我一定会收到Unable to create a constant value of type 错误,因为查询在数据库中。最后我不得不加入一个连接,这可能更接近原生 SQL。但我仍然确信我可以实施您的解决方案。我错过了什么?
  • 另一点。我把自己绊倒了,因为我想从我的存储库构建我的查询,每个存储库都代表一个表。使用这种模式,每个 Repo 都会实例化一个 MainEntities 上下文。从这个案例中收集,我是否可以推断出 Repo 模式仅在仅对一个表执行查询时才有用?我是否错误地实施了该模式?这可能是另一个 SO 问题。
  • 假设adminGroupUserIDsIQueryable<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 上下文。
猜你喜欢
  • 2011-01-25
  • 1970-01-01
  • 2018-06-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-18
  • 1970-01-01
  • 2012-02-07
相关资源
最近更新 更多