Первым делом нужно проверить, как соотносятся отношения сущностей. Как правило, свойства навигации должны быть помечены как виртуальные, чтобы EF мог использовать их в качестве прокси. Еще одна оптимизация заключается в том, что если объекты ссылаются на подкатегорию, то, поскольку подкаталоги ссылаются на категорию, этим объектам не нужны оба. Вам понадобятся оба, если подкатегории не являются обязательными. Наличие обоих не обязательно вызовет проблемы, но это может привести к сценариям, в которых категория замораживания не соответствует категории подкатегории замораживания. (Видел более, чем достаточно ошибок, подобных этому, в зависимости от того, замерз ли код.
Деталь ошибки, похоже, указывает на то, что EF знает о сущностях, но не рассказывает об их отношениях. Вы должны убедиться, что у вас есть картографические данные, чтобы сообщить EF о взаимосвязи между Frosting и SubCategory. EF может вывести некоторые из них автоматически, но мое предпочтение всегда должно быть явным. (Я ненавижу сюрпризы!)
public class FrostingConfiguration : EntityTypeConfiguration<Frosting>
{
public FlavorConfiguration()
{
ToTable("Flavors");
HasKey(x => x.FlavorId)
.Property(x => x.FlavorId)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
HasRequired(x => x.SubCategory)
.WithMany()
.Map(x => x.MapKey("SubCategoryId");
}
}
Поскольку у вашей сущности Flavor, по-видимому, нет свойства для SubCategoryId, это помогает сообщить EF об этом. EF, возможно, сможет сделать это, но с идентификаторами и автоматическими соглашениями об именах, которые он ищет, я не пытаюсь вспомнить, что работает автоматически.
Теперь, если это EF Core, вы можете заменить оператор .Map()
на:
.ForeignKey("SubCategoryId");
, который установит свойство тени для FK.
Если SubCats не обязательны, замените HasRequired
на HasOptional
. WithMany()
просто означает, что, хотя Flavor ссылается на подкатегорию, SubCategory не поддерживает список вариантов.
Следующим предостережением является передача сущностей за пределы области DBContext, в которую они были загружены. Хотя EF поддерживает отсоединение сущностей от одного контекста и повторное присоединение их к другому, я бы сказал, что эта практика почти всегда гораздо больше проблем, чем она того стоит. Преобразование сущностей в POCO ViewModels / DTO, а затем их загрузка по требованию снова при выполнении обновлений проще и менее подвержено ошибкам, чем попытка их присоединения. Состояние данных, возможно, изменилось между моментом их первоначальной загрузки и повторным присоединением, поэтому отказоустойчивый код должен обрабатывать этот сценарий в любом случае. Это также избавляет от необходимости возиться с измененным состоянием в наборах сущностей. Хотя может показаться эффективным не загружать объекты во второй раз, принимая модели представлений, вы можете оптимизировать чтение намного эффективнее, только извлекая и транспортируя значимые данные, а не целые графы объектов. (Системы обычно читают гораздо больше, чем обновляют). Даже для операций с интенсивным обновлением вы можете использовать ограниченный контекст для представления больших таблиц в виде небольших простых объектов, чтобы более эффективно загружать и обновлять несколько ключевых полей.