如何使用Entity Framework Code First Fluent API仅在连接表上级联删除
我正在尝试使用Entity Framework Code First Fluent API映射现有数据库。 我在与多对多关系和级联删除的情况下苦苦挣扎。
这是我的两个POCO课程:
public class Foo { public int FooId; public string FooDescription; public IList Bars; } public class Bar { public int BarId; public string BarDescription; }
现在,我只有一个从Foo
到Bar
的导航属性。 那是因为在我真实的场景中,任何人从Bar
到Foo
都没有意义。 从Foo
到Bar
的关系实际上是0,n,这意味着Foo
一个实例不需要Bar
实例。
我现有的数据库在这两个表之间有一个连接表。 此表如下所示:
create table Foo_Bar( FooId int not null, BarId int not null );
因为我不想在我的项目中创建这样的POCO类,所以我映射了这样的表:
modelBuilder.Entity() .HasMany(t => t.Bars) .WithMany() .Map(m => { m.ToTable("Foo_Bar"); m.MapLeftKey("FooId"); m.MapRightKey("BarId"); });
这适用于插入。 实体在Foo上插入,然后在现有的Foo_Bar
表上插入。
但是当我删除Foo
,我想删除连接表上的记录,但不删除子表上的记录。 意思是我想要删除Foo_Bar
记录,但不要将此级联扩展到Bar
。
这样的映射可能吗? 我应该提一下,在我的上下文中,我删除了OneToManyCascadeDeleteConvention
和ManyToManyCascadeDeleteConvention
因为99%的时间我不会使用级联删除。 这是一个具体情况。
通过跟踪Entity Framework生成的SQL,我还注意到如果我检索一个Foo
实例并将其中的所有Bars设置为EntityState.Deleted,EF将删除Foo_Bar
和Bar
两个记录。 我要提到的最后一件事是我在一个断开连接的场景中工作。
我尝试搜索这个,但似乎我没有使用正确的关键字,因为在这种情况下我找不到任何人。 在这一点上,我看到的唯一解决方案是Map
一个FooBar
类,但我希望有一种方法可以做到这一点。
– 编辑
看来我的删除方法起初是错误的。 当我尝试删除时,我没有传递Foo
的实例,其中的Bar
列表已填满。 在更改之后,Entity Framwork为列表中的每个Bar
创建一个delete语句。 我仍然有更新问题,如同时添加和删除项目。 会做更多的测试并发布在这里。
提前致谢。
但是当我删除Foo时,我想删除连接表上的记录,但不删除子表上的记录。 意思是我想要删除Foo_Bar上的记录,但不要将此级联扩展到Bar。
这样的映射可能吗?
这实际上是唯一可行的映射。 您不能将级联删除扩展到Bar
表,因为在关系中(从数据库模式的角度来看), Foo_Bar
连接表是关系中的依赖项 ,而Bar
是主体 。 通常,cacscading delete仅在删除主体时有效,但在删除从属时不会生效。
因此,您不必担心在删除Foo
时可能会删除Bar
,并且您不必为此应用任何特殊设置。
但是,当您删除ManyToManyCascadeDeleteConvention
时,您会遇到问题。 它针对整个模型进行全局操作,并且没有选项可以针对特定的多对多关系再次启用级联删除。 (对于多对多关系,没有WillCascadeOnDelete(true)
,就像一对多关系或一对一关系一样。)
您确定在模型中真的需要删除ManyToManyCascadeDeleteConvention
吗? 我从来没有遇到一个模型,当删除其中一个连接的实体( Foo
或Bar
)时, 不删除连接表中的相关条目是有意义的。