Я получаю ошибку с каскадным удалением в отношении "один ко многим" в EF Code First
Сначала я использую код EF, и я генерирую свои коды с помощью EF 4.X DbContext Fluent Generator T4, поэтому теперь у меня есть 2 объекта poco (я изменил свои списки на BindingList<T>
использовать привязку в winForms):
public partial class Parent
{
public Parent()
{
this.Childs = new BindingList<Childs>();
}
int _ParentId;
public int ParentId { get; set; }
BindingList<Child> _Childs;
public virtual BindingList<Child> Childs { get; set; }
}
public partial class Child
{
int _ChildId;
public int ChildId { get; set; }
int _ParentId;
public int ParentId { get; set; }
Parent_Parent;
public virtual Parent Parent { get; set; }
}
а также мои файлы отображения как:
public Parent_Mapping()
{
this.HasKey(t => t.ParentId);
this.ToTable("Parent");
this.Property(t => t.ParentId).HasColumnName("ParentId");
}
public Child_Mapping()
{
this.HasKey(t => t.ChildId);
this.ToTable("Child");
this.Property(t => t.ChildId).HasColumnName("ChildId");
this.Property(t => t.ParentId).HasColumnName("ParentId").IsRequired();
this.HasRequired(t => t.Parent)
.WithMany(t => t.Childs)
.HasForeignKey(t=>t.ParentId)
.WillCascadeOnDelete(true);
}
и в моем DbContext у меня есть эти коды:
public partial class MyContext : DBContext
{
static MyContext()
{
Database.SetInitializer<MyContext>(null);
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<IncludeMetadataConvention>();
modelBuilder.Configurations.Add(new Parent_Mapping());
modelBuilder.Configurations.Add(new Child_Mapping());
}
public DbSet<Parent> Parents { get; set; }
public DbSet<Child> Childs { get; set; }
}
поэтому у меня есть отношение "один ко многим" с включенным каскадным удалением.
но когда я хочу удалить родительский объект, я получил эту ошибку:
{
"Cannot insert the value NULL into column 'ParentId', table 'MyDB.dbo.Child';
column does not allow nulls. UPDATE fails.\r\nThe statement has been terminated."
}
Когда я использовал EF Profiler для мониторинга, я увидел, что EF хочет обновить дочернюю таблицу, чтобы установить для ParentId значение Null, вместо этого удалить родительскую сущность!:
update [dbo].[Child]
set
[ParentId] = null,
where ([ChildId] = 2 /* @1 */)
где моя ошибка?
1 ответ
ИМХО причина в том, что у вас есть ребенок, загруженный вместе с вашим родителем. В таком случае вы также должны удалить ребенка. Если вы удалите только родительский EF, просто установите отношение в нуль. EF не сделает каскадное удаление. Каскадное удаление используется только в базе данных и только тогда, когда у вас не загружен дочерний элемент. Если у вас загружен дочерний элемент, его обновление выполняется до удаления родительского объекта, и возникает это исключение.
Если вы хотите, чтобы поведение было похоже на каскадное удаление для загруженных объектов, вы должны использовать нечто, называемое идентифицирующим отношением (у вашего дочернего объекта будет первичный ключ, состоящий из его идентификатора и идентификатора родителя).