在EF中将外键id设置为null非常慢

时间:2012-05-16 14:42:47

标签: c# entity-framework

我通过存储库模式使用实体框架,并且具有显着且令人惊讶的性能问题。我已经完成了剖析,所以我非常了解会发生什么,我只是不知道该怎么办。

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

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

中间线(employee.CompanyId = null)需要花费大量时间才能完成(大约30秒)。时间不用在提交行上。

通过分析,我找到了运行这部分自动生成的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;
}

我真的好奇为什么禁用延迟加载会更快(以及可能产生的副作用)

3 个答案:

答案 0 :(得分:2)

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

你能做什么:

  • 修改模板并删除与fixup相关的所有代码
  • Employees
  • 中删除反向导航属性(Company
  • 在此操作之前关闭延迟加载 - context.ContextOptions.LazyLoadingEnabled = false

答案 1 :(得分:0)

嗯,这很奇怪;另一方面,而不是将公司Id设置为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();

答案 2 :(得分:0)

自动更改检测出现问题。

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

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

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

这解释了Chaneg Tracking概念: