【问题标题】:Cascading delete on a Entity Framework Child that requires Either Parents but not both在需要父级但不是两者的实体框架子级上级联删除
【发布时间】:2018-07-20 18:48:40
【问题描述】:
我有两个类与孩子有一对多的关系。孩子只能有一个父母,不能同时有两个。
我怎样才能做到这一点?如果是这样,如果任一父级被删除,我怎样才能使其级联删除?
class Parent1
{
public int Id {get;set;}
public IList<Child> Children {get;set;}
}
class Parent2
{
public int Id {get;set;}
public IList<Child> Children {get;set;}
}
class Child
{
public int Id {get;set;}
public int? Parent1Id {get;set;}
public int? Parent2Id {get;set;}
}
【问题讨论】:
标签:
entity-framework
entity-framework-6
ef-code-first
code-first
【解决方案1】:
您可以在 EF 中设置一个实体验证来检查这一点,但您还需要在数据库中创建一个 CHECK CONSTRAINT 以确保该规则得到实际执行。
此外,您必须在子实体上同时具有 FK 属性和导航属性才能通过 EF 强制执行此操作。在新的 Child 上,Navigation 属性可以为非 null,但尚未填充 FK 属性。在现有实体上,将加载 FK 属性,但可能不会加载导航属性。 EG
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Data.Entity.Validation;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ef62test
{
class Program
{
public class Parent1
{
public int Id { get; set; }
public virtual ICollection<Child> Children { get; } = new HashSet<Child>();
}
public class Parent2
{
public int Id { get; set; }
public virtual ICollection<Child> Children { get; } = new HashSet<Child>();
}
public class Child
{
public int Id { get; set; }
public int? Parent1Id { get; set; }
public virtual Parent1 Parent1 { get; set; }
public int? Parent2Id { get; set; }
public virtual Parent2 Parent2 { get; set; }
}
public class MyDbContext : DbContext
{
public DbSet<Parent1> Parent1s { get; set; }
public DbSet<Parent2> Parent2s { get; set; }
public DbSet<Child> Children { get; set; }
protected override DbEntityValidationResult ValidateEntity(DbEntityEntry entityEntry, IDictionary<object, object> items)
{
var errors = new List<DbValidationError>();
if (entityEntry.Entity is Child child )
{
if ((child.Parent1Id != null || child.Parent1 != null)
&& (child.Parent2Id != null || child.Parent2 != null))
{
var error = new DbValidationError("Parent2id", "Parent2id must be null when Parent1id is null");
errors.Add(error);
}
}
return new DbEntityValidationResult(entityEntry, errors);
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
}
}
static void Main(string[] args)
{
Database.SetInitializer(new DropCreateDatabaseAlways<MyDbContext>());
using (var db = new MyDbContext())
{
db.Database.Log = s => Console.WriteLine(s);
var p1 = new Parent1();
var p2 = new Parent2();
var c = new Child();
p1.Children.Add(c);
p2.Children.Add(c);
db.Parent1s.Add(p1);
db.Parent2s.Add(p2);
db.Children.Add(c);
db.SaveChanges();
}
Console.WriteLine("Hit any key to exit.");
Console.ReadKey();
}
}
}