【发布时间】:2021-11-06 00:41:58
【问题描述】:
我有 Parent 和 Child 的一对多关系来存储一些数据。我想使用 Npgsql.EntityFrameworkCore.PostgreSQL 包将这些数据存储在 PostgreSQL 中。 Parent 映射到一个表,而 Child 在数据库中存储为 Parent 表的 json 列。
public class Parent
{
public int Id { get; set; }
[Column(TypeName = "json")]
public ICollection<Child> Children { get; set; }
}
public class Child
{
public int Id { get; set; }
public string Name { get; set; }
}
当我尝试使用以下代码将子实体添加到现有父实例时,SaveChangesAsync 不会在数据库上生成更新命令。
var child = new Child(){Id = 0, Name = "Name"};
var parent = await DataContext.Parent.SingleOrDefaultAsync(f => f.Id == 1);
parent.Children.Add(child);
await DataContext.SaveChangesAsync();
为了触发更新命令,我必须在调用 SaveChangesAsync 之前将父实体的 State 设置为 Modified。
var entry = DataContext.Entry<Parent>(parent);
entry.State = EntityState.Modified;
这是预期的行为还是我错过了什么?
更新: 正如@SvyatoslavDanyliv 建议的那样,当我使用从 List 派生的类 EqualityCollection 并覆盖 Object.Equals 时,不要使用 ICollection > 如下:
public class EqualityCollection<T> : List<T>
{
public override bool Equals(object? obj)
{
if (obj != null && obj.GetType() == typeof(EqualityCollection<T>))
return this.Equals(obj as EqualityCollection<T>);
return false;
}
public bool Equals(EqualityCollection<T> obj)
{
return this.SequenceEqual(obj ?? throw new InvalidOperationException());
}
public override int GetHashCode()
{
return base.GetHashCode();
}
}
更改检测不会检测到属性的更改,并且不会触发更新命令。
【问题讨论】:
-
ICollection下隐藏了哪个类? -
列表、数组、哈希集?无论如何,正如我从 EF Core 资源中看到的,正确的更改检测类型应该支持
IStructuralEquatable,或者您应该覆盖Equals和GetHashCode。因此,请尝试基于List创建您的集合,并覆盖 Equals。 -
检查你的 Equals 是。叫。在上面设置断点。
-
我明白了。让我检查一下 EF Core 源,也许有办法为快照注入自定义 ValueComparer。
-
好吧,我找到了文档。定义转换时很容易使用ValueComparer docs.microsoft.com/en-us/ef/core/modeling/…
标签: entity-framework-core npgsql