EF学习杂记33:EF中的级联删除是怎么运作的


假设你有下面所示的具有级联删除关系的数据库表结构:

CascadeDeleteInDatabase

这里的级联删除规则是,当删除Category的时候,应当级联删除与之相关联的Products。

如果你根据上面的数据表结构生成相应的EF模型,像下面这样,看上去没有什么异常,这里并没有显示与级联删除相关的信息:

ProductCategory

但是如果你看一下后台的CSDL文件,你就会发现有一点不同的地方,如下面文件所示:

<Association Name="FK_Products_Categories">
<End Role="Categories" Type="TipsModel.Store.Categories" Multiplicity="1">
<OnDelete Action="Cascade" />
</End>
<End Role="Products" Type="TipsModel.Store.Products" Multiplicity="*" />
<ReferentialConstraint>
<Principal Role="Categories">
<PropertyRef Name="ID" />
</Principal>
<Dependent Role="Products">
<PropertyRef Name="CategoryID" />
</Dependent>
</ReferentialConstraint>
</Association>

关注一下节点<OnDelete>,这里指明了这个级联删除的关系,当Category被删除的时候,相关联的Products“或许”会也被删除。

我在这里故意使用了“或许”这个词,而没有用”应该”是因为EF在这里的删除并不会作用于数据库。

EF在这里只负责ObjectContxt在执行了SaveChanges()方法之后的正确性,换句话说,EF在这里只是试图在数据库发生了级联删除动作以后,去同步相对应的ObjectContext。

如果你使用SQlProfiler来查看,你就会注意到,当EF发起Delete对父对象发起Delete请求的时候,它也会同时会对已经加载入ObjectContext中的依赖子对象向数据库发起Delete请求。

这里所发生的事情的本质是EF期望在数据库中删除父对象的时候,删除所有数据库中与其相关的子对象,所以他向自己发起了一个额外的Delete请求以删除所有已经加载入ObjectContext中的依赖对象。

上面的表述有一些拗口,但总结起来就是EF只会删除已经加载入内存的依赖对象,而不会对未存在于内存中的以来对象进行任何操作。

下面是两条黄金法则:

  1. 如果你要在你的EF模型中增加级联删除功能,一定要记住同时也要在数据库中添加相关的规则。
  2. 如果由于某些原因,你一定要违背规则1,在数据库中没有添加相应的级联删除规则,级联删除将只会对已经加载如ObjectContext中的依赖对象起作用,换句话说,即使级联删除的规则在EF模型中存在,如果依赖子对象没有被加载到ObjectContext中,即使发起了级联删除动作,相关联的子对象由于不在ObjectContext中,相关的数据库删除指令也不会被传递到数据库中。
  3. 我们不推荐规则2的这种做法。

在我们努力保持ObjectContext和database之间的数据同步的时候,我们针对多级级联删除的尝试可能会失败,比如你有如下的对象关系:
Category –> Product –> Order

有可能会出现这样的情况,假设在ObjectContext有一个具有关联性的Category和Order,但其中间对象Product对象并没有被加载进ObjectContext,这个时候如果你实施了规则1,在ObjectContext和Database中都添加了级联删除规则,当你删除Category对象的时候,在数据库中,按照规则,相关的Product和Order都会被删除,但是在ObjectContext中,由于Product对象没有被加载,级联删除规则将会被阻断,Order对象将仍然存在,状态仍将是unchanged,尽管Category已经被删除,这将使ObjectContext和database产生不同步的情况。

智能推荐

注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
© 2014-2019 ITdaan.com 粤ICP备14056181号  

赞助商广告