gpt4 book ai didi

c# - 为什么 EF 尝试使用单个或多个 SaveChanges() 插入实例两次?

转载 作者:太空宇宙 更新时间:2023-11-03 17:00:26 25 4
gpt4 key购买 nike

我有以下类结构

class A { long Id { get; set; } ICollection<B> ManyB { get; set; } }
class B { long Id { get; set; } C { get; set; } }
class C { long Id { get; set; } Name { get; set; } }

用一个看起来像这样的实例图

object graph

当我添加一个 A 的实例时,它在 ManyB 中有两个不同的 B 实例引用相同的 C 实例,当我调用此代码时,EF 尝试插入两次 C:

var a = CreateItAsDescribedAbove();
context.Add(a)
context.SaveChanges();

上面的所有对象都是新的;也就是说,它们不是数据库中已有的实体。当我将代码更改为以下内容时,我仍然有相同的行为:

var a = CreateItAsDescribedAbove();
A.ManyB
.Select(b => b.C)
.DistinctBy(c => c.Id)
.ForEach(c => context.Add(c));
context.SaveChanges();
context.Add(a)
A.ManyB
.Select(b => b.C)
.ForEach(c => context.Entry(c).State = EntityState.Unchanged);
context.SaveChanges();

我本以为在先前的添加之后强制 EF 将对象视为未更改应该可行,但它们似乎被忽略了。

我如何说服 EF 保存我的 C 实例一次?请注意,我不能简单地取消其中一个 B.C,因为这样就不会插入其中一个关系。我不关心在一次提交中执行此操作。什么都管用。

最佳答案

使用对象和等于运算符时存在一个问题:当在哈希表或字典键中使用对象时,覆盖 GetHashCode 方法非常重要。

EF 使用字典作为内部上下文。

尝试为您的类覆盖 GetHashCode,并且您必须确保为相同的实例对象返回相同的结果。

编辑:

EF 使用带有多个字典的内部 ObjectStateManager:AddedEntityStore、ModifiedEntityStore、DeletedEntityStore、UnchangedEntityStore (Dictionary<'EntityKey, EntityEntry>)。当 EF 在“SaveChanges”上搜索这些字典中的实体时,使用字典的 TryGetValue 方法。因此,为简洁起见,这是代码:

private int FindEntry(TKey key)
{
if ((object) key == null)
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
if (this.buckets != null)
{
int num = this.comparer.GetHashCode(key) & int.MaxValue;
for (int index = this.buckets[num % this.buckets.Length]; index >= 0; index = this.entries[index].next)
{
if (this.entries[index].hashCode == num && this.comparer.Equals(this.entries[index].key, key))
return index;
}
}
return -1;
}

我们所有人都可以看到这句话:this.comparer.GetHashCode(key)

这与将 GetHashCode 与 Dictionary 和 HashTable 一起使用一样相关。请参阅 Dino Esposito 帖子:http://software2cents.wordpress.com/2014/04/12/hash-codes-and-equality-in-the-net-framework/

关于c# - 为什么 EF 尝试使用单个或多个 SaveChanges() 插入实例两次?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37119851/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com