2

我正在通过存储库模式使用实体框架,并且有一个重要且令人惊讶的性能问题。我已经完成了分析,所以我对发生的事情有一个很好的了解,我只是不知道该怎么做。

这是我的代码的本质(简化):

var employee = Repositories.Employees.FirstOrDefault(s => s.EmployeeId == employeeId);
employee.CompanyId = null;
Repositories.Commit();

中间线 ( employee.CompanyId = null) 需要惊人的时间才能完成(大约 30 秒)。时间没有花在 Commit 行上。

通过分析,我找到了运行这部分自动生成的 EF 代码的原因:

if (previousValue != null && previousValue.**Employees**.Contains(this))
{
    previousValue.Employees.Remove(this);
}

这并没有真正帮助我,但它确实证实了问题出在 EF 上。我真的很想知道该怎么做。我可以以其他方式(存储过程)更新列,但我真的更愿意在任何地方使用 EF。

我无法轻松编辑 EF 设置,因此我更喜欢不涉及此内容的建议。

更新 我通过直接对数据库运行 SQL 解决了这个问题,然后从上下文中刷新对象以确保 EF 会立即检测到此更改。

public void SetCompanyNull(Guid employeeId)
{
    _ctx.ExecuteStoreCommand("UPDATE Employee SET CompanyId = NULL WHERE EmployeeId = N'" + employeeId + "'");
    _ctx.Refresh(RefreshMode.StoreWins, _ctx.Employees.FirstOrDefault(s => s.EmployeeId == employeeId));
}

更新 2 我还通过暂时禁用延迟加载解决了这个问题。

var lazyLoadDisabled = false;
if (_ctx.ContextOptions.LazyLoadingEnabled)
{
   _ctx.ContextOptions.LazyLoadingEnabled = false;
   lazyLoadDisabled = true;
}

this.GetEmployeeById(employeeId).CompanyId = null;
this.SaveChanges();

if (lazyLoadDisabled)
{
    _ctx.ContextOptions.LazyLoadingEnabled = true;
}

我真的很好奇为什么禁用延迟加载会更快(以及这可能有哪些副作用)

4

3 回答 3

2

这是 EF POCO 生成器模板中的问题,在某些情况下会导致意外的延迟加载。此模板为导航属性生成修复代码,因此如果您更改一侧的导航属性,它会在内部转到已更改关系的另一端并尝试修复关系以使其保持一致。不幸的是,如果您的相关对象没有加载导航属性,则会触发延迟加载。

你可以做什么:

  • 修改模板并删除所有与fixup相关的代码
  • Employees您的Company
  • 在此操作之前关闭延迟加载 -context.ContextOptions.LazyLoadingEnabled = false
于 2012-05-16T14:50:57.057 回答
0

好吧,这很奇怪;另一方面,不是将 companyId 设置为 null;您可以尝试将其从集合中删除。就像是;

var company = Repositories.Companies.Include("Employee").FirstOrDefault(s => s.Employee.Any(q => q.EmployeeId == employeeId));
company.Employees.Remove(q => company.Employees.Where(l => l.EmployeeId == employeeId).SingleOrDefault());
Repositories.Commit();
于 2012-05-16T14:48:43.377 回答
0

自动更改检测有问题。

正如 Ladislav Mrnka 所指出的,当您更改关系中涉及的属性时,它会尝试将更改转移到相关实体。

您可以通过在执行该操作时在上下文中禁用自动“更改跟踪”来避免这种情况。

这解释了一个类似的问题及其解决方案:

这一般解释了 Chaneg 跟踪概念:

于 2012-05-16T15:23:34.033 回答