c# - 为什么 Entity Framework Core 2 Attach() 方法不会导致跟踪后续更改?
问题描述
我正在将应用程序移植到 EF Core 2,并且我想对对象进行大量部分更新。但是,我不想先查询这些对象(我已经知道它们在那里,我不在乎我要更改的属性的先前值是什么;查询它们是浪费往返数据库)。
在 EF6 中,我只需使用适当的键值创建一个对象、附加它、进行更改并保存,它会使用跟踪的更改在 SQL 中生成更新。但在 EF Core 2 中,这不起作用;实体状态保持不变。我知道我可以手动告诉跟踪器我已经更改了某些属性,但这很混乱有两个原因:在部分更新之前必须查询对象的代码不必这样做,所以它很混乱,还有那个模式会让我两次指定每个非常潮湿的属性。
一个人为的例子,假设 MyDbContext 继承了从 Scaffold-DbContext 生成的 DbContext:
//This is a model class for a table (id uniqueidentifier PRIMARY KEY, data int)
public partial class Record
{
public Guid id { get; set; }
public bool data { get; set; }
}
一些导致数据库不更新的代码:
using (var db = new MyDbContext()) {
var rec = new Record {
id = new Guid('bc372788-5a96-4ada-a2e0-c604d1abed92')
}
db.Attach(rec);
rec.data = false;
db.SaveChanges();
}
一些确实会导致更新的代码,但如果多个属性已更改,则会变得非常混乱:
using (var db = new MyDbContext()) {
var rec = new Record {
id = new Guid('bc372788-5a96-4ada-a2e0-c604d1abed92'),
data = false
}
db.Attach(rec).Property(x => x.data).IsModified = true;
db.SaveChanges();
}
为了更加强调,一些代码进行了无用的查询,但确实像我想要的那样更新了数据库:
using (var db = new MyDbContext()) {
var rec = db.Record.Single(x => x.id == new Guid('bc372788-5a96-4ada-a2e0-c604d1abed92'));
rec.data = false;
db.SaveChanges();
}
有什么方法可以做到这一点,这样我就不必在更新现有记录之前对其进行查询,而且 EF Core 2 也可以跟踪我对记录所做的更改?
解决方案
它不起作用,因为我是个傻瓜。bool 的默认 CLR 值为 false,因此,新构造的对象已经具有 data = false。更改跟踪器运行,当然检测到它仍然是错误的,并且不生成任何更改。
一种解决方案是将值设置为非默认值,以便它看起来已更改:
using (var db = new MyDbContext()) {
var rec = new Record {
id = new Guid('bc372788-5a96-4ada-a2e0-c604d1abed92'),
data = true
}
db.Attach(rec);
rec.data = false;
db.SaveChanges();
}
另一种方法是在类中使用可为空的类型(如果合适),另一种方法仍然是声明该属性已使用 .IsModified 进行修改,如上所述。
推荐阅读
- openscenegraph - 无法在 FBX 文件中嵌入纹理
- sharepoint - SharePoint WSP 部署未完成,因为 SharePoint 更新
- fortran - 带有格式化换行符的单个 Fortran WRITE 语句?
- html - 应用 xsl 时遇到问题:选择
- hdf5 - 如何在 HDF5 中存储标记的联合
- c# - 为什么 GridFS 查询在 C# 中返回空值/默认值
- javascript - 如何避免在更改和单击之间触发错误功能
- python - 如何使用 Oauth2.0 解码不透明的访问令牌
- java - SAML 2.0 RelayState 参数:如何在 WSO2 IS 中向登录表单添加额外字段?
- python - 如何使用python根据标签计算对象数量?