У меня есть следующая модель:
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?). Кроме того, в коде я добавляю индексные страницы книги, но изначально они имеют пустые идентификаторы.