gpt4 book ai didi

c# - EntityFramework 在执行更新查询时非常慢

转载 作者:太空狗 更新时间:2023-10-30 01:16:51 25 4
gpt4 key购买 nike

我们正在调查 EF 6.1.3 运行缓慢的性能问题,我们无法找出可能导致该问题的原因。

数据库上下文初始化为:

Configuration.ProxyCreationEnabled = false;
Configuration.AutoDetectChangesEnabled = false;
Configuration.ValidateOnSaveEnabled = false;

我们已将性能问题隔离到以下方法:

protected virtual async Task<long> UpdateEntityInStoreAsync(T entity,
string[] changedProperties)
{
using (var session = sessionFactory.CreateReadWriteSession(false, false))
{
var writer = session.Writer<T>();
writer.Attach(entity);
await writer.UpdatePropertyAsync(entity, changedProperties.ToArray()).ConfigureAwait(false);
}
return entity.Id;
}

changedProperties 列表中有两个名称,EF 正确生成了仅更新这两个属性的更新语句。

此方法会被重复调用(以处理一组数据项),大约需要 15-20 秒才能完成。

如果我们用下面的方法替换上面的方法,执行时间会下降到 3-4 秒:

protected virtual async Task<long> UpdateEntityInStoreAsync(T entity,
string[] changedProperties)
{
var sql = $"update {entity.TypeName()}s set";
var separator = false;
foreach (var property in changedProperties)
{
sql += (separator ? ", " : " ") + property + " = @" + property;
separator = true;
}
sql += " where id = @Id";
var parameters = (from parameter in changedProperties.Concat(new[] { "Id" })
let property = entity.GetProperty(parameter)
select ContextManager.CreateSqlParameter(parameter, property.GetValue(entity))).ToArray();
using (var session = sessionFactory.CreateReadWriteSession(false, false))
{
await session.UnderlyingDatabase.ExecuteSqlCommandAsync(sql, parameters).ConfigureAwait(false);
}
return entity.Id;
}

在编写器(存储库实现)上调用的 UpdatePropertiesAsync 方法如下所示:

public virtual async Task UpdatePropertyAsync(T entity, string[] changedPropertyNames, bool save = true)
{
if (changedPropertyNames == null || changedPropertyNames.Length == 0)
{
return;
}

Array.ForEach(changedPropertyNames, name => context.Entry(entity).Property(name).IsModified = true);
if (save)
await context.SaveChangesAsync().ConfigureAwait(false);
}
}

EF 做了什么完全破坏了性能?我们可以做些什么来解决这个问题(除了使用另一个 ORM 之外)?

最佳答案

通过计时代码,我能够看到 EF 花费的额外时间是在将对象附加到上下文的调用中,而不是在更新数据库的实际查询中。

通过消除所有对象引用(在附加对象之前将它们设置为 null 并在更新完成后恢复它们),EF 代码在“可比较的时间”(5 秒,但有很多记录代码)到手写解决方案。

所以看起来 EF 有一个“错误”(有些人可能称之为功能)导致它递归地检查附加的对象,即使更改跟踪和验证已被禁用。

更新:EF 7 似乎已通过允许您在调用 Attach 时传入 GraphBehavior 枚举来解决此问题。

关于c# - EntityFramework 在执行更新查询时非常慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33872925/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com