Entity framework 未检测到 c# 中的 jsonb 属性更改

Entity framework not detecting jsonb properties changes in c#

我正在使用 Entity Framework Core 和 npgsql postgresql for 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

如何实现这样的事情?

自动更改检测意味着 EF Core 会在加载 属性 时拍摄 JSON 文档的快照(复制整个树),然后对 JSON 文档进行完整的结构比较每当调用 SaveChanges 时,原始树和当前树。由于这在性能方面可能非常繁重,因此默认情况下不会这样做。

但是,如果您希望这样做,您可以创建一个值比较器来精确地实现这个 - see the EF docs on how to do that. I've opened an issue 在 Npgsql 提供程序 repo 上,以防有人希望贡献这个。

出于性能原因,我建议在属性更改时手动标记属性,这与您所做的类似。请注意,您将整个实体实例标记为已更改 - 因此将保存所有属性。您可以使用以下仅标记 JSON 属性:

ctx.Entry(entry).Property(e => e.SomeJsonProperty).IsModified = true;