将实体添加到另一个实体的子级集合时重复。感谢被覆盖的等于?

时间:2018-06-26 13:18:59

标签: c# entity-framework-core equality

public class Foo
{
    public int Id { get; set; }
    public ICollection<Bar> Bars{get;set;}
}

public class Bar
{
    public int Id { get; set; }
    public int FooId { get; set; }

    public override bool Equals(object obj)
    {
        var bar= obj as Bar;
        return bar != null &&
               Id == bar.Id;
    }

    public override int GetHashCode()
    {
        return 2108858624 + Id.GetHashCode();
    }
}

public class SomeClass
{
    DbContext _context = ...; // injected via DI

    public void AddNewBarToFoo(int fooId)
    {
        // Option 1
        // result: foo.Bars contains two items
        Foo foo = _context.Foos
               .Where(f => f.id == fooId)
               .Include(f => f.Bars)
               .FirstOrDefault();
        foo.Bars.Add(new Bar());
        _context.SaveChanges();

        // Option 2
        // result: foo.Bars contains one item
        Bar bar = new Bar();
        bar.FooId = FooId;
        _context.Bars.Add(bar);
        _context.SaveChanges();

        // Option 3:
        // Remove _context.SaveChanges() from Option 1

        // Option 4:
        // Remove the Id comparison from Bar.Equals()
    }
}

今天,我注意到使用Entity Framework Core有点奇怪。在AddNewBarToFoo的{​​{1}}方法中,我想向Foos集合中添加一个新的Bar。最初,我使用Option 1,但是我注意到,在调用SomeClass之后,foo.Bars将两次包含新的Bar。
我注意到,删除对SaveChanges的调用不会添加第二个Bar,并且仍然可以正确保留Bar。使用选项2也会按预期工作。

我发现这是一种非常奇怪的行为,经过一番调查,我发现这样做的原因是我取代了Bar的SaveChanges方法,并且我使用了ID来检查是否相等。
Equals方法中删除ID比较,否则使用Option 1可以按预期工作:Foo.Bars仅包含一次新的Bar。

我现在实际上有两个问题:

  1. 实体框架两次添加相同栏的原因是什么?
    我想它会一次将新的Bar添加到上下文中,为其提供一个ID,然后再次遇到它(以某种方式?),但是此实例仍然具有ID 0,因此,与我的Equals方法中的第一个实例不同。

  2. 我在覆盖的Equals方法中使用ID是否出错?还是在代码中向Foo添加新Bar?覆盖Equals是不好的做法吗?
    简而言之:做什么是我尝试做的“正确”方法?

0 个答案:

没有答案