问题 使用EF Code First方法时MVC .Net级联删除


我是MVC的新手,我在级联删除方面遇到了麻烦。对于我的模型我有以下两个类:

    public class Blog
    {
        [Key]
        public int Id { get; set; }
        [Required]
        public string Name { get; set; }
        [DisplayFormat()]
        public virtual ICollection<BlogEntry> BlogEntries { get; set; }
        public DateTime CreationDateTime { get; set; }
        public string UserName { get; set; }
    }

    public class BlogEntry
    {
        [Key]
        public int Id { get; set; }
        [Required]
        public string Title { get; set; }
        [Required]
        public string Summary { get; set; }
        [Required]
        public string Body { get; set; }
        public List<Comment> Comments { get; set; }
        public List<Tag> Tags { get; set; }
        public DateTime CreationDateTime { get; set; }
        public DateTime UpdateDateTime { get; set; }
        public virtual Blog ParentBlog { get; set; }

    }

对于我的控制器,我设置他关注删除帖子:

[HttpPost, ActionName("Delete")]
public ActionResult DeleteConfirmed(int id)
{
    Blag blog = db.Blogs.Find(id);

    foreach (var blogentry in blog.BlogEntries)
    {
        //blogentry = db.BlogEntries.Find(id);
        db.BlogEntries.Remove(blogentry);
    }
    db.Blogs.Remove(blog);
    db.SaveChanges();
    return RedirectToAction("Index");
}

问题是无论如何都不会工作; 我读过这篇文章 但我似乎只适用于关系是一对一的模型,所以我迷失在这里,我到处搜索,找不到解决这个问题的方法,如果有人能指出我错过了什么会非常好:),提前谢谢,再次,原谅我的诺言,我刚刚开始,但想要解决一个大项目,能够学到很多东西。


9423
2018-02-11 16:11


起源



答案:


这是因为默认情况下EF不会强制执行可选关系的级联删除。模型中的关系被推断为可选。

您可以添加不可为空的标量属性(BlogId)FK

public class BlogEntry
{
    [Key]
    public int Id { get; set; }
    [Required]
    public string Title { get; set; }
    [Required]
    public string Summary { get; set; }
    [Required]
    public string Body { get; set; }
    public List<Comment> Comments { get; set; }
    public List<Tag> Tags { get; set; }
    public DateTime CreationDateTime { get; set; }
    public DateTime UpdateDateTime { get; set; }

    public int ParentBlogId { get; set; }

    public virtual Blog ParentBlog { get; set; }
}

或者使用流畅的API配置它

   modelBuilder.Entity<BlogEntry>()
            .HasRequired(b => b.ParentBlog)
            .WithMany(b => b.BlogEntries)
            .WillCascadeOnDelete(true);

15
2018-02-11 16:33



好极了 ! :D,谢谢它的工作!,非常感谢,我只是不知道流畅的API,但似乎是一个很好的方法来做这些东西,顺便说一句¿我能用数据注释获得这种行为吗? - Q_ro
@Q_ro数据注释具有有限的一组功能。 - Eranga


答案:


这是因为默认情况下EF不会强制执行可选关系的级联删除。模型中的关系被推断为可选。

您可以添加不可为空的标量属性(BlogId)FK

public class BlogEntry
{
    [Key]
    public int Id { get; set; }
    [Required]
    public string Title { get; set; }
    [Required]
    public string Summary { get; set; }
    [Required]
    public string Body { get; set; }
    public List<Comment> Comments { get; set; }
    public List<Tag> Tags { get; set; }
    public DateTime CreationDateTime { get; set; }
    public DateTime UpdateDateTime { get; set; }

    public int ParentBlogId { get; set; }

    public virtual Blog ParentBlog { get; set; }
}

或者使用流畅的API配置它

   modelBuilder.Entity<BlogEntry>()
            .HasRequired(b => b.ParentBlog)
            .WithMany(b => b.BlogEntries)
            .WillCascadeOnDelete(true);

15
2018-02-11 16:33



好极了 ! :D,谢谢它的工作!,非常感谢,我只是不知道流畅的API,但似乎是一个很好的方法来做这些东西,顺便说一句¿我能用数据注释获得这种行为吗? - Q_ro
@Q_ro数据注释具有有限的一组功能。 - Eranga


不知道你在这里尝试做什么,但你有一条记录,所以不确定为什么你试图在这里循环是我的删除代码:

public ActionResult Delete(int id)
    {
        try {
        Products products = context.Products.Single(x => x.productId == id);
        return View(products);
        }
        catch (Exception ex)
          {
            ModelState.AddModelError("",ex.Message);
            CompileAndSendError(ex);
            return View(new Products());
          }
    }

    //
    // POST: /Products/Delete/5

    [HttpPost, ActionName("Delete")]
    public ActionResult DeleteConfirmed(int id)
    {
        try {
        Products products = context.Products.Single(x => x.productId == id);
        context.Products.Remove(products);
        context.SaveChanges();
        return RedirectToAction("Index");
        }
        catch (Exception ex)
          {
            ModelState.AddModelError("",ex.Message);
            CompileAndSendError(ex);
            return RedirectToAction("Index");
          }
    }

1
2018-02-11 16:26



好吧,想想这样,每个产品都有一个类别,我想在删除产品时删除这些类别,因为现在,如果我删除了一个产品,我的类别仍然会在那里数据库。 - Q_ro
是的,但你的代码应该只显示包含类别的代码,你应该还有一个类别和项目的启用/禁用列,基本上你不应该删除任何东西,但只是标记为已删除这可以减少以后引用ID的问题但是没有更长的存在。如果你想要虽然你可以从对象中获取类别ID,删除类别然后删除原始对象,但你应该真正编写代码来更好地处理它而不是仅删除所有内容:-) - davethecoder
感谢您的建议,我会记住这一点:)。 - Q_ro