我希望以1:1的关系进行级联删除,其中我将多个实体引用为一个。问题导致数据库更新错误
介绍FOREIGN KEY约束' FK_dbo.CategoryArticles_dbo.Articles_Article_Id'在表格' CategoryArticles'可能会导致循环或多个级联路径。指定ON DELETE NO ACTION或ON UPDATE NO ACTION,或修改其他FOREIGN KEY约束。
RoutingSeo
实体用于将seo friendly url
存储在数据库中供以后使用。我的问题显然是M:N
和Article
之间的Category
关系。有什么办法可以解决这个问题吗?
以下是我的模特实体
public class Article : IEntity<int>
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<Category> Categories { get; set; }
[Required]
public virtual RoutingSeo RoutingSeo { get; set; }
public int RoutingSeoId { get; set; }
}
public class Category : IEntity<int>
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<Article> Articles { get; set; }
[Required]
public virtual RoutingSeo RoutingSeo { get; set; }
public int RoutingSeoId { get; set; }
}
public class SpecificProduct : IEntity<int>
{
public int Id { get; set; }
public string Name { get; set; }
[Required]
public RoutingSeo RoutingSeo { get; set; }
public int RoutingSeoId { get; set; }
}
public class RoutingSeo : IEntity<int>
{
public int Id { get; set; }
public string SeoRoute { get; set; }
public Article Article { get; set; }
public SpecificProduct SpecificProduct { get; set; }
public Category Category { get; set; }
}
这是我的流畅api代码,其中我指定了级联删除
modelBuilder.Entity<Article>()
.HasRequired(x => x.RoutingSeo)
.WithOptional(x=>x.Article)
.WillCascadeOnDelete();
modelBuilder.Entity<Category>()
.HasRequired(x => x.RoutingSeo)
.WithOptional(x=>x.Category)
.WillCascadeOnDelete();
modelBuilder.Entity<SpecificProduct>()
.HasRequired(x => x.RoutingSeo)
.WithOptional(x=>x.SpecificProduct)
.WillCascadeOnDelete();
答案 0 :(得分:1)
你是对的,这是Article
和Category
之间的多对多关系:一个Article
有零个或多个Categories
,每个{{1}可以由零个或多个Category
使用。
如果您删除了Articles
,则无法自动删除其Article
,因为其他Categories
可能会使用Category
,即使它现在还没有使用,实体框架不知道你明天是否想要使用它。毕竟,您指定零或更多Articles
可能会使用每个Category
。
同样,如果您删除Articles
,则实体框架无法自动删除属于此类别的Category
。
这与一对多的关系不同。例如,如果您与Articles
及其Book
之间存在一对多关系,那么每个Pages
都有零个或多个Book
以及每个Pages
}只属于一个Page
。
如果您删除Book
,则实体框架知道它应该自动删除Book
的所有Pages
,这些Book
都是Pages
的外键{{ 1}}。如果实体框架只删除BookId
,那么我们会有一堆Book
外键值指向不存在的Pages
。因此,在一对多关系中,实体框架可以在删除时级联。
从好的方面来说,您可以删除Book
的最后Article
,并保持Category
完好无损。明天您可以添加使用此Category
的新Article
。
因此,如果您要删除文章,则必须手动将其从其使用的“类别”中删除:
符合标准命名约定的多对多:
Category
不要忘记宣布您的ICollections虚拟!
class Article
{
public int Id {get; set;}
// an Article belongs to zero or more Categories:
public virtual ICollection<Category> Categories {get; set;}
...
}
class Category
{
public int Id {get; set;}
// a Category is used by zero or more Articles:
public virtual ICollection<Article> Articles{get; set;}
...
}
您不必提及联结表,实体框架会自动为您提供,但如果您希望class MyDbContext : DbContext
{
public class DbSet<Article> Articles {get; set;}
public class DbSet<Category> Categories {get; set;}
}
使用Articles
,则不必将其用于联接{1}}或Categories
及其Categories
,只需使用Articles
注意:由于Categories不是预期的Category复数,因此您必须告诉实体框架正确的表名。超出了这个问题的范围。
删除文章,但保留它所属的所有类别:
ICollections
实体框架将自动执行正确的连接,并从每个类别中删除articleToRemove。但是,类别不会被删除。
事实上,类别表内部根本没有变化。带有Article.Id的所有记录都将从联结表中删除。