简体   繁体   English

如何使用Entity Framework Code First Fluent API仅在连接表上级联删除

[英]How to cascade delete only on join table using Entity Framework Code First Fluent API

I'm trying to map an existing database using Entity Framework Code First Fluent API. 我正在尝试使用Entity Framework Code First Fluent API映射现有数据库。 I'm struggling on a situation with a many-to-many relationship and cascade delete. 我在与多对多关系和级联删除的情况下苦苦挣扎。

Here's my two POCO classes: 这是我的两个POCO课程:

public class Foo
{
  public int FooId;
  public string FooDescription;
  public IList<Bar> Bars;
}
public class Bar
{
  public int BarId;
  public string BarDescription;
}

For now, I only have a navigation property from Foo to Bar . 现在,我只有一个从FooBar的导航属性。 That's because in my real scenario, it doesn't make sense for anyone to go from Bar to Foo . 那是因为在我的真实场景中,任何人从BarFoo都没有意义。 The relationship from Foo to Bar is actually 0,n which means one instance of Foo do not require instances of Bar . FooBar的关系实际上是0,n这意味着Foo一个实例不需要Bar实例。

My existing database has a join table between those two tables. 我现有的数据库在这两个表之间有一个连接表。 This table looks like this: 此表如下所示:

create table Foo_Bar(
FooId int not null,
BarId int not null
);

Because I prefer to not create such a POCO class in my project, I mapped the table like this: 因为我不想在我的项目中创建这样的POCO类,所以我映射了这样的表:

modelBuilder.Entity<Foo>()
  .HasMany(t => t.Bars)
  .WithMany()
  .Map(m =>
  {
    m.ToTable("Foo_Bar");
    m.MapLeftKey("FooId");
    m.MapRightKey("BarId");
  });

That works perfectly for inserts. 这适用于插入。 Entity insert on Foo and then on the existing Foo_Bar table. 实体在Foo上插入,然后在现有的Foo_Bar表上插入。

But when I delete a Foo , I would like to delete the records on the join table but not on the child table. 但是当我删除Foo ,我想删除连接表上的记录,但不删除子表上的记录。 Meaning I want to delete records on Foo_Bar but not to extend this cascade to Bar . 这意味着我想要删除Foo_Bar记录,但不要将此级联扩展到Bar

Is such a mapping possible? 这样的映射可能吗? I should mention that on my context I removed both OneToManyCascadeDeleteConvention and ManyToManyCascadeDeleteConvention because 99% of the times I won't be using cascade delete. 我应该提一下,在我的上下文中,我删除了OneToManyCascadeDeleteConventionManyToManyCascadeDeleteConvention因为99%的时间我不会使用级联删除。 This is one specific situation. 这是一个具体情况。

By tracing the SQL generated by Entity Framework, I also noticed that if I retrieve a Foo instance and set all Bars inside it to EntityState.Deleted, EF will delete both records in Foo_Bar and Bar . 通过跟踪Entity Framework生成的SQL,我还注意到如果我检索一个Foo实例并将其中的所有Bars设置为EntityState.Deleted,EF将删除Foo_BarBar两个记录。 One last thing I should mention is that I'm working in a disconnected scenario. 我要提到的最后一件事是,我正处于一个断开连接的场景中。

I tried to search this over but it seems I'm not using the right keywords as I could not find anyone in such a situation. 我试图搜索它,但似乎我没有使用正确的关键字,因为在这种情况下我找不到任何人。 At this point the only solution I see is to Map a FooBar class but I'd hope there's a way to do this. 在这一点上,我看到的唯一解决方案是Map一个FooBar类,但我希望有一种方法可以做到这一点。

--Edit - 编辑

It appears that my approach to delete was wrong at first. 看来我的删除方法起初是错误的。 When I tried deleting I wasn't passing the instance of Foo with its list of Bar filled. 当我尝试删除时,我没有传递Foo的实例,其中Bar列表已填满。 After that change, Entity Framwork creates a delete statement for every Bar on the list. 在更改之后,Entity Framwork为列表中的每个Bar创建一个delete语句。 I still have problems with updating like adding and removing items at the same time. 我仍然遇到更新问题,例如同时添加和删除项目。 Will do more tests and post here. 会做更多的测试并发布在这里。

Thanks in advance. 提前致谢。

But when I delete a Foo, I would like to delete the records on the join table but not on the child table. 但是当我删除Foo时,我想删除连接表上的记录,但不删除子表上的记录。 Meaning I want to delete records on Foo_Bar but not to extend this cascade to Bar. 这意味着我想要删除Foo_Bar上的记录,但不要将此级联扩展到Bar。

Is such a mapping possible? 这样的映射可能吗?

This is actually the only mapping that is possible. 这实际上是唯一可行的映射。 You cannot extend cascading delete to the Bar table because in the relationship (from database schema perspective) the Foo_Bar join table is the dependent in the relationship and Bar is the principal . 您不能将级联删除扩展到Bar表,因为在关系中(从数据库模式角度来看) Foo_Bar连接表是关系中的依赖项 ,而Bar主体 Generally cacscading delete is only in effect if you delete the principal but not when you delete the dependent. 通常,cacscading delete仅在删除主体时有效,但在删除依赖时则不起作用。

So, you don't need to worry that a Bar could be deleted when you delete a Foo and you don't have to apply any special setting for this. 因此,您不必担心在删除Foo时可能会删除Bar ,并且您不必为此应用任何特殊设置。

But you have a problem when you have removed the ManyToManyCascadeDeleteConvention . 但是,当您删除ManyToManyCascadeDeleteConvention时,您会遇到问题。 It acts globally for the whole model and there is no option to turn on cascading delete again for a specific many-to-many relationship. 它针对整个模型进行全局操作,并且没有选项可以针对特定的多对多关系再次启用级联删除。 (There is no WillCascadeOnDelete(true) for many-to-many relationship like there is one for one-to-many or one-to-one relationships.) (对于多对多关系,没有WillCascadeOnDelete(true) ,就像有一对多关系或一对一关系一样。)

Are you sure that removing the ManyToManyCascadeDeleteConvention is really required in your model? 您确定在模型中真的需要删除ManyToManyCascadeDeleteConvention吗? I never encountered a model where it would make sense to not delete the related entries in the join table when one of the joined entities ( Foo or Bar ) is deleted. 我从未遇到一个模型,当删除其中一个连接的实体( FooBar )时, 删除连接表中的相关条目是有意义的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM