【发布时间】:2021-12-26 12:28:50
【问题描述】:
使用 EF 更新记录,但没有相应更新。我只想更新不为空且已修改的字段。以前我是这样做的:
_context.Attach(exist).CurrentValues.SetValues(t);
它将更新所有字段,我不希望这样。
我的代码有什么遗漏的吗?
public virtual async Task<T> UpdateAsync(T t, object key)
{
if (t == null)
return null;
T exist = await _context.Set<T>().FindAsync(key);
if (exist != null)
{
// _context.Attach(exist).CurrentValues.SetValues(t);
_context.Attach(exist);
var entry = _context.Entry(t);
Type type = typeof(T);
PropertyInfo[] properties = type.GetProperties();
foreach (PropertyInfo property in properties)
{
if (property.GetValue(t, null) == null)
{
entry.Property(property.Name).IsModified = false;
}
}
// _context.Attach(exist).CurrentValues.SetValues(t);
await _context.SaveChangesAsync();
}
return exist;
}
【问题讨论】:
-
这段代码有什么意义?您不需要任何这些来更新对象。加载对象,修改它们的属性,调用
SaveChangesAsync以立即保存所有更改。 DbContext 已经是一个多实体的通用工作单元。 DbSet 已经是一个通用存储库。更改已被跟踪。并且.Set<T>()可能会导致旧 EF Core 版本出现性能问题 -DbContext将缓存所有已定义 DbSet 属性的元数据。只有 EF Core 5(或 6?)也向Set<T>()添加了缓存 -
In previous I'm doing like this: _context.Attach(exist).CurrentValues.SetValues(t);为什么要这样做?如果您修改由 EF Core 本身加载的对象,则不需要Attach。该对象已被附加和跟踪。您只需要使用Attach来持久化一个分离的对象,例如一个使用PUT 发送到服务器的对象。如果您只想修改已更改的属性,则需要找到这些属性。一种方法是使用PATCH而不是PUT,并且只将修改后的属性发送到您的控制器。否则,您必须实际加载对象并检查更改
标签: c# entity-framework .net-core