【问题标题】:Querying many times with Entity Framework mixes the results使用 Entity Framework 多次查询会混合结果
【发布时间】:2014-05-21 05:10:49
【问题描述】:

我有一个实体实例,我尝试使用同一个实例查询数据库 2 次或更多次。

myAppDbEntities db = new myAppDbEntities();
List<user> usersList = db.users.Where(c => c.userid == usrID).ToList();

foreach (user u in usersList)
{
    u.items = db.items.Where(c => c.userid == u.id && c.date == today).ToList();
    item extraItem = db.items.Where(c => c.userid == u.id && c.date == yesterday).FirstOrDefault();
    //...
}

return usersList;

问题是,当返回 usersList 时,extraItem 被包含在用户的项目列表中。

我正在获取的所有数据都好像是相互附加的一样。

谢谢

【问题讨论】:

  • 如果您注释掉 'item extraItem' 行,它仍然会发生吗?
  • 不,如果我不使用“db”查询其他任何内容,结果就是我想要的。我还注意到如果我重新初始化 db = new myAppDbEntities();它也有效。我担心这是否是正确的做法?在每个新查询之前重新初始化数据库实例。 @EricScherrer
  • 我被难住了,但另一方面,这并不是奇怪的事情,这就是为什么我通常不从我的资源访问中返回 EF 对象,而是使用像 AutoMapper 这样的框架来返回 DTO。跨度>
  • 我正在尝试重新创建 - 用户和项目之间的数据库中是否有任何外键?
  • 我怀疑 u.items 是一个指针,指向加载到该用户 ID 的项目集合中的任何实体。因此,如果您从 db 加载它,它将存在于 u.items 集合中。这就是我在 EF 时代的回忆,现在正在验证。

标签: c# asp.net entity-framework linq-to-entities


【解决方案1】:

如果你在用户和项目之间定义了一个外键,usersList 是一个指向 myAppDbEntities.users 的指针,所以无论你事先从数据库中获取什么,如果你去一个用户并询问它的项目,实体框架会去去数据库并获取所有项目,除非你当时给它一个过滤器。

为了停止这种行为并明确控制加载哪些实体,您必须 Detatch 上下文中的实体。这是我使用 EF 6.0 测试此行为的代码示例:

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        var parents = GetParents();

        foreach (var parent in parents)
        {
            Console.WriteLine(@"Parent: " + parent.ParentId);

            foreach (var child in parent.Children)
            {
                Console.WriteLine(@"Child: " + child.ChildId);
            }
        }
    }

    private List<Parent> GetParents()
    {
        var context = new EFTestDBEntities();

        var parentList = context.Parents.Where(x => x.ParentId == 1).ToList();

        foreach (var parent in parentList)
        {
            // Commenting out the following line makes the above Console.WriteLines enumerate all children
            ((IObjectContextAdapter)context).ObjectContext.Detach(parent);
            parent.Children = context.Children.Where(x => x.ChildId == 1).ToList();
        }

        return parentList;
    }

【讨论】:

    【解决方案2】:

    解决方案是使用 AsNoTracking() 进行您想要独立的查询:

    myAppDbEntities db = new myAppDbEntities();
    List<user> usersList = db.users.Where(c => c.userid == usrID).ToList();
    
    foreach (user u in usersList)
    {
        u.items = db.items.Where(c => c.userid == u.id && c.date == today).ToList();
        item extraItem = db.items.Where(c => c.userid == u.id && c.date == yesterday).**AsNoTracking()**.FirstOrDefault();
        //...
    }
    
    return usersList;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多