我将Entity Framework Core和npgsql postgresql用于Entity Framework Core。 并且我正在使用.net core 3
我的问题是,当我尝试从MyTableClass更新MyTableRelated元素并将上下文保存到数据库时,没有检测到更改。
例如,假设我们有以下类:
public class MyTableClass
{
public int Id { get; set; }
[Column(TypeName = "jsonb")]
public virtual List<MyTableRelated> Data { get; set; }
}
public class MyTableRelated
{
public int Id { get; set; }
public string prop1 { get; set; }
public string prop2 { get; set; }
}
和一些类似的代码(这不是实际的代码,仅是为了获得思想):
var context = dbContext;
var newMyTableClass = new MyTableClass() {
Id = 1;
};
var newMyTableRelated = new MyTableRelated(){
Id=1;
prop1 = "";
prop2 = "";
}
newMyTableClass.Data.Add(newMyTableRelated);
context.SaveChanges();
这有效,并且条目保存在数据库中。
现在在应用程序中的某个位置,我想访问该条目并更改数据上的值:
var context = dbContext;
var updateMyTableClass = context.MyTableClass.FirstOrDefault(x => x.Id == 1);
var tableRelated = updateMyTableClass.Data.FirstOrDefault(y => y.Id == 1);
tableRelated.prop1 = "prop1";
tableRelated.prop2 = "prop2";
context.SaveChanges();
我想这会改变数据库的值,就像其他类型的属性一样。但是什么也没发生。
我找到的解决方案正在使用此方法:
var entry = context.Entry(updateMyTableClass);
if (entry.State == EntityState.Unchanged)
{
entry.State = EntityState.Modified;
}
这更多是针对该情况的临时解决方案。
然后如何使EF自动检测jsonb
属性的更改?
有人指出我应该看一下科斯粒状锁。 https://www.martinfowler.com/eaaCatalog/coarseGrainedLock.html
该如何实现?
答案 0 :(得分:1)
自动更改检测将意味着EF Core在加载属性(复制整个树)时会为JSON文档拍摄快照,然后在调用SaveChanges时对原始树和当前树进行完整的结构比较。由于这在性能方面可能非常繁琐,因此默认情况下不会这么做。
但是,如果您愿意,可以创建一个值比较器来精确地实现它-see the EF docs on how to do that。 I've opened an issue在Npgsql提供程序回购上,以防有人希望提供。
出于性能方面的考虑,我建议您在属性更改时手动对其进行标记,这与您所做的类似。请注意,您将整个实体实例标记为已更改-因此将保存所有属性。您可以使用以下内容仅标记JSON属性:
ctx.Entry(entry).Property(e => e.SomeJsonProperty).IsModified = true;