首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在EF中将外键id设置为null非常慢。

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

Stack Overflow用户
提问于 2012-05-16 14:42:46
回答 3查看 330关注 0票数 2

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

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

代码语言:javascript
复制
var employee = Repositories.Employees.FirstOrDefault(s => s.EmployeeId == employeeId);
employee.CompanyId = null;
Repositories.Commit();

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

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

代码语言:javascript
复制
if (previousValue != null && previousValue.**Employees**.Contains(this))
{
    previousValue.Employees.Remove(this);
}

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

我不能轻松地编辑EF设置,所以我更喜欢不涉及这一点的建议。

Update I解决了这个问题,方法是直接对数据库运行,然后从上下文中刷新对象,以确保EF立即检测到此更改。

代码语言:javascript
复制
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 I也通过临时禁用延迟加载来解决这个问题。

代码语言:javascript
复制
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;
}

我真的很好奇,为什么在禁用延迟加载的情况下,加载速度要快得多(以及这会产生哪些副作用)。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-05-16 14:50:57

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

你能做的是:

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

Stack Overflow用户

发布于 2012-05-16 14:48:43

嗯,这很奇怪;另一方面,您可以尝试从集合中删除它,而不是将companyId设置为null。类似的东西;

代码语言:javascript
复制
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();
票数 0
EN

Stack Overflow用户

发布于 2012-05-16 15:23:34

你在自动变化检测方面有问题。

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

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

这就解释了一个类似的问题及其解决办法:

  • 在EF 4.1中使用DbContext第12部分:自动检测更改

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

  • 变更跟踪
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10620966

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档