EF Core - Какая правильная конфигурация? - PullRequest
1 голос
/ 17 марта 2020

У меня есть следующая модель:

public class Book 
{
    public Guid Id { get; set; }

    public List<IndexPage> IndexPages { get; set; }
}

public class IndexPage 
{ 
    public Guid Id { get; set; }
    public List<IndexWord> Words { get; set; }

    public int IndexType { get; set; }
    public Guid BookId { get; set; }
}

public class IndexWord {
    public Guid Id { get; set; }
    public String Value { get; set; }

    public IndexPageId { get; set; }
}

Это настроено со следующей конфигурацией:

public class BookConfiguration : IEntityTypeConfiguration<Book>
{
    public void Configure(EntityTypeBuilder<Book> builder)
    {
         builder.ToTable("Books");
         builder.HasKey(b => b.Id);

         builder.HasMany(b => b.IndexPages)
                .WithOne()
                .HasForeignKey(b => b.BookId);
    }
}

public class IndexPageConfiguration : IEntityTypeConfiguration<IndexPage>
{
    public void Configure(EntityTypeBuilder<IndexPage> builder)
    {
         builder.ToTable("IndexPages");
         builder.HasKey(ip => new { ip.BookId, ip.IndexType });

         builder.HasMany(ip => ip.IndexWords)
                .WithOne()
                .HasForeignKey(iw => iw.IndexPageId)
                .HasPrincipalKey(ip => ip.Id);

        builder.HasIndex(ip => ip.Id).IsUnique();
    }
}

public class IndexWordConfiguration : IEntityTypeConfiguration<IndexWord>
{
    public void Configure(EntityTypeBuilder<IndexWord> builder)
    {
         builder.ToTable("IndexWords");
         builder.HasKey(iw => iw.Id);

         builder.Property(iw => iw.Value).IsRequired();
    }
}

Некоторый контекст; Запросы выполняются с помощью AsNoTracking(), и обновление вызывается следующим образом:

DbContext.Set<Book>.Update(book);

Если книга обновляется, все страницы индекса заменяются новым набором страниц индекса. При первом вызове update все кажется работает правильно и вставляет строки. Однако при вызове во второй раз возникает исключение ограничения первичного ключа; Это имеет смысл, однако я ожидал, что старые индексные страницы будут удалены и новые индексные страницы будут вставлены. Из-за того, что первичный ключ существует и вызывается обновление, not Add .

Причина, по которой составной ключ состоит в том, что книга может иметь только фиксированное подмножество индексных страниц. это также причина, по которой использовался HasPrincipalKey.

При использовании только идентификатора IndexPage в качестве ключа в конфигурации. Связь между книгой существует, но она просто продолжает вставлять новые индексные страницы поверх старых индексных страниц (наверное, из-за AsNoTracking?). Кроме того, в коде я добавляю индексные страницы книги, но изначально они имеют пустые идентификаторы.

Ответы [ 2 ]

1 голос
/ 17 марта 2020

Если я правильно понимаю, старые IndexPage сущности не заменяются новыми, когда вы пытаетесь обновить?

Вы упомянули, что вы используете No Tracking для своих запросов. Без отслеживания исходной сущности, возвращенной по вашему запросу, EF Core не может сказать, что сущность была изменена. Если вы хотите, чтобы новые IndexPage объекты заменяли старые, вам нужно отслеживать запросы и настраивать поведение удаления для ваших отношений.

Вы можете посмотреть в документации EF Core справочную информацию о необходимых отношения и удалить поведение. Будьте внимательны при настройке этих вещей на правильных объектах, чтобы в итоге не удалить все, удалив IndexPage.

. Позволяет отслеживать изменения и настраивать, если требуются отношения и их поведение удаления. Это должно достичь sh того, чего вы хотите достичь.

https://docs.microsoft.com/en-us/ef/core/modeling/relationships?tabs=fluent-api%2Cfluent-api-simple-key%2Csimple-key#manual -конфигурация

1 голос
/ 17 марта 2020

Согласно документам Update начинается отслеживание объекта. Это означает, что если вы измените его, достаточно вызвать DbContext.SaveChanges() для его сохранения. Если вы вызываете Update на отслеживаемом объекте, он пытается вставить его.

...