为什么会收到指定的LINQ表达式包含对与不同上下文关联的查询的引用?

时间:2018-10-02 22:46:02

标签: c# entity-framework linq

例外:
System.NotSupportedException:'指定的LINQ表达式包含对与不同上下文关联的查询的引用。'

代码:

IEnumerable<EntityIdName> entitiesIDs = 
    (from a in afimDB.UNITES
     select new EntityIdName { entityId = (int)a.UNIT_ID, entityName = a.UNIT_NAME })
    .AsEnumerable();

var usersWithEntities = (
    from user in imdb.AspNetUsers
    select new
    {
        UserId = user.Id,
        Username = user.UserName,
        Email = user.Email,
        EntityNames = (
            from a in imdb.UserEntities
            join b in imdb.AspNetUsers on a.UserID equals b.Id
            where user.Id == a.UserID
            select new 
            { 
                entity = (
                    from q in entitiesIDs 
                    where q.entityId == 2 
                    select q.entityName)
                    .ToArray()
            })
            .ToList() 
        })
        .AsEnumerable()
        .Select(p => new Users_in_Entities_ViewModel()
        {
            UserId = p.UserId,
            Username = p.Username,
            Email = p.Email,
            Entity = string.Join(",", p.EntityNames)
        });

2 个答案:

答案 0 :(得分:0)

这部分查询没有任何意义:

EntityNames = (
    from a in imdb.UserEntities
    join b in imdb.AspNetUsers on a.UserID equals b.Id
    where user.Id == a.UserID
    select new 
    { 
        entity = (
            from q in entitiesIDs 
            where q.entityId == 2 
            select q.entityName)
            .ToArray()
    })
    .ToList() 
})

为什么要从表中选择数据,然后再连接到另一个表以完全将其全部丢弃?

这可以简化很多:

string unitNames = string.Join(", ", afimDB.UNITES
    .Where(a => a.UNIT_ID == 2)
    .Select(a => a.UNIT_NAME));

var usersWithEntities = (
    from user in imdb.AspNetUsers
    select new Users_in_Entities_ViewModel
    {
        UserId = user.Id,
        Username = user.UserName,
        Email = user.Email,
        Entity = unitNames 
    });

答案 1 :(得分:0)

您收到的错误是由于:

IEnumerable<EntityIdName> entitiesIDs = 
    (from a in afimDB.UNITES
     select new EntityIdName { entityId = (int)a.UNIT_ID, entityName = a.UNIT_NAME })
    .AsEnumerable();

AsEnumerable无法完全执行EF表达式。为此,您需要使用ToList()

IEnumerable<EntityIdName> entitiesIDs = 
    (from a in afimDB.UNITES
     select new EntityIdName { entityId = (int)a.UNIT_ID, entityName = a.UNIT_NAME })
    .ToList();

现在,您将拥有一个EntityIdName的POCO列表,该列表可在第二个EF表达式中引用。 EF将针对无法加入afimDB上下文的表达式的imDB上下文执行第二个查询。

编辑:演示行为和调整。这只是一个使用2个DbContext实例范围的示例,以演示来自一个上下文的查询不能在另一个上下文中使用。

    using (var context2 = new TestDbContext())
    {
        var ids = context2.Customers
            .Where(x => x.Name == "Fred")
            .Select(x => x.CustomerId)
            .AsEnumerable();
        using (var context = new TestDbContext())
        {
            var customers = context.Customers.Where(x => ids.Contains(x.CustomerId))
                .ToList();
        }
    }

上面提到的“通过指定的LINQ表达式包含对与不同上下文相关联的查询的引用”对客户的检索失败。

    using (var context2 = new TestDbContext())
    {
        var ids = context2.Customers
            .Where(x => x.Name == "Fred")
            .Select(x => x.CustomerId)
            .ToList(); // <- The .ToList you need
        using (var context = new TestDbContext())
        {
            var customers = context.Customers.Where(x => ids.Contains(x.CustomerId))
                .ToList();
        }
    }

按预期工作。 .ToList()将针对数据库的第一个查询执行到POCO列表中,该列表在第二个查询的范围内是安全的。 .AsEnumerable()不会。

请保持评论的建设性,并在拒绝投票之前尝试一下。