2016-06-14 103 views
0

如果我在.NET MVC项目中使用实体框架(数据库上下文中的dbsets和模型等)有这样的关系。了解.net mvc(实体框架)中特定关系中的级联删除?

class A { 
    contains a list of class C objects (one-to-many) 
} 

class B { 
contains a list of class C objects (one-to-many), often many of the 
same class C entries which class A uses aswell 
} 

class C { 
    contains class D elements 
} 

class D { } 

所以,主要的问题是,A级是一个模式,我想作为数据经常删除其只应该用于固定的时间量(当时它是由cron作业删除)存在,但由于某种原因,当我删除类A条目时,它似乎混淆了类C和类D之间的关系,从数据库中的类C条目中删除了类D项。

是否有某种方法可以删除我的类中的条目数据库表,同时确保它完全保留所有其他表而无一例外?

我已阅读禁用级联删除,但说实话,我很困惑我应该如何理解在这个特定的上下文中发挥什么奇怪的关系,我不太确定我应该是什么禁用它。

我希望这个例子有意义我试图尽可能简单地解释它。

+0

你可以发表一些关于你如何做EF映射的更多细节? –

回答

1

默认情况下,EF启用了OneToManyCascadeDeleteConvention。这工作就像通过在表之间的外键上设置SQL级联删除一样。当主要对象被删除时,任何外部键入该对象的对象也将被删除。因此,在您的示例中,删除A时,它也将删除集合中的所有对象。而且由于级联,它还将删除所有这些对象的集合中的所有D对象(假设您的意思是C包含一对多的D对象集合)。

但是,OneToManyCascadeDeleteConvention仅适用于外键字段设置为必需的情况。将其设置为空(如下例所示)应禁用约定。

public class ObjectA 
{ 
    public int ObjectAId { get; set; } 
    public virtual ICollection<ObjectC> ObjectCCollection { get; set; } 
} 

public class ObjectC 
{ 
    public int? ObjectAId { get; set; } 
    public virtual ObjectA ObjectA { get; set; } 
} 

这就是说,也可以选择性地使用一个EntityTypeConfiguration实体配置期间除去ObjectA之间的级联ObjectC

internal class ObjectCMap : EntityTypeConfiguration<ObjectC> 
{ 
    public ObjectCMap() 
    { 
     this.HasOptional(o => o.ObjectA).WithMany(o => o.ObjectCCollection).WillCascadeOnDelete(false); 
    } 
} 

,然后用在DbContext

modelBuilder.Configurations.Add(new ObjectCMap()); 

模型构建器注册它如果ObjectC外键字段不能为空,但是,SQL会当您尝试抛出一个外键错误删除ObjectA

+0

如何设置外键?现在,我只是在“many”模型中使用虚拟icollection 和虚拟来创建一对多关系,实体框架自己命名外键(使用自己的外键名创建列)。我是否应该将EF为我选择的列的名称声明为类中的变量? – ObedMarsh

+0

在这种情况下,您可以使用上面显示的EntityTypeConfiguration。 HasOptional将使外键可以为空。 – Kevin

+0

只是为了完整起见,你有第二个选择,就像你所描述的那样,在你的模型中创建一个属性来保存外键。这将在上面的示例中继续“ObjectC”,按照惯例,属性名称应该与链接到的表上的id字段具有相同的名称,在本例中为“ObjectA”。如果您需要属性名称不同,则可以使用ForeignKeyAttribute设置要用作外键的自定义属性名称。这是一个资源,显示我的意思:http://tektutorialshub.com/data-annotations-foreignkey-attribute-entity-framework/ – Kevin