14

这是我的第一个 EF 项目,请多多包涵。

在更新诸如 Department 之类的实体时,您将其从上下文中拉出,更新其值并调用 context.SaveChanges。但是,如果您更新 Department.Employees,EF 不会觉得这很有趣。

我搜索并想出了在连接字符串中设置 Multipleactiveresultsets=true 的选项,但想知道是否:

  • 这是推荐的方式吗?
  • 这是否会对性能产生不利影响/我应该注意什么?
4

1 回答 1

34

仅当您想在同一连接上并行执行多个查询时,才需要启用 MARS。如果您执行以下操作,则会发生这种情况:

/* Foreach uses an iterator over the resultset of your query, but the query is not fetched
   immediately, instead the iterator internally triggers fetching for single
   processed record from opened data reader. Because of that the query and the reader
   are active until the iteration is over. */
foreach (var department in context.Departments.Where(...))
{
    /* The first query is still active on the connection but now you are executing
       lazy loading of all related employees =>. You are executing a second query and,
       without MARS, you will get an exception. */
    var employee = department.Employees.FirstOrDefault(...);
}

如何避免这种情况?

  • 使用急切加载而不是延迟加载:context.Departments.Include(d => d.Employees)
  • 在使用延迟加载之前实现整个部门的结果集。这意味着不访问循环内的员工。
  • 启用 MARS,上面提到的示例将简单地工作

这是推荐的方式吗?这是否会对性能产生不利影响/我应该注意什么?

这取决于您要解决的问题。如果您有多个部门要处理,访问他们的员工集合将触发每个部门的单独查询。这被称为 N+1 问题 - 您有 N 个部门和一个查询来获取它们,并且对于每个部门,您将执行一个额外的查询 => N+1 个查询。对于大量部门来说,这将是一个性能杀手。

急切加载也不是一个防弹解决方案。它也会影响性能。有时您只需要执行单独的查询来获取所有必要的部门,并执行单独的查询来获取所有必要的员工。如果您关闭了延迟加载,它应该会修复您的关系并为您正确填写员工属性。顺便说一句,我对 Data UserVoice 提出了一个建议,即开箱即用地支持此功能。

于 2012-05-07T09:05:41.220 回答