Дублируется при добавлении сущности в дочернюю коллекцию другой сущности. Благодаря переопределенным Равным? - PullRequest
0 голосов
/ 26 июня 2018
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 SomeClass я хочу добавить новый Bar в коллекцию Foos. Первоначально я использовал Вариант 1, но заметил, что после вызова SaveChanges foo.Bars будет содержать новый Bar дважды.
Я заметил, что удаление вызова на SaveChanges не добавит второй Бар и все еще сохранит Бар правильно. Использование варианта 2 также работает как ожидалось.

Я обнаружил, что это довольно странное поведение, и после небольшого исследования я обнаружил, что причина этого в том, что я отверг метод Equals Бара и использовал Id для проверки на равенство.
Удаление сравнения идентификаторов из метода Equals и использование в противном случае варианта 1 работает должным образом: Foo.Bars содержит новый Bar только один раз.

У меня сейчас два вопроса:

  1. По какой причине Entity Framework добавляет один и тот же столбец дважды?
    Я предполагаю, что он добавляет новый Bar в контекст один раз, давая ему Id, а затем снова встречает его (как-нибудь?), Но этот экземпляр все еще имеет Id 0 и, следовательно, считается отличным от первого для моего Equals метода.

  2. Был ли я неправ в использовании идентификатора в моем переопределенном Equals методе? Или в коде для добавления нового бара в Foo? Это плохая практика переопределять Equals?
    Короче говоря: что такое «правильный» способ сделать то, что я пытался сделать?

...