0

我刚刚开始使用 MVC 4,并且在我的应用程序中遇到了一个错误,我需要一些帮助来修复。

我有一个 Author & Book 表。Author 表是父表,您可以有多个 Books 与每个作者关联。

在我尝试删除仍然分配有书籍的作者之前,一切都运行良好。发生这种情况时,我在 SaveChanges() 收到一条错误消息,说明:

DELETE 语句与 REFERENCE 约束“FK_Book_Author”冲突。

该错误非常有意义,但我希望应用程序向用户提供一个很好的错误消息,而不是简单地爆炸。

如何在模型中定义这种关系,以便在删除与关联的子项的记录时不会导致应用程序爆炸?

作者类

public partial class Author
{
    public Author()
    {
        this.Book = new HashSet<Book>();
    }

    [Key]
    public int AuthorId { get; set; }

    [Required]
    public string AuthorName { get; set; }

    public virtual Book Book { get; set; }
}

书类

public partial class Book
{
    [Key]
    public int BookId { get; set; }

    [Required]
    public string BookName { get; set; }

    [Required]
    [ForeignKey("Author")]
    public string AuthorId { get; set; }
}

模型

我最近开始尝试覆盖 OnModelCreating,但它似乎没有任何影响。

public partial class BookEntities : DbContext
    {
        public BookEntities()
            : base("name=BookEntities")
        {
        }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Book>().HasRequired(p => p.Author)
                .WithMany(b => b.Books)
                .HasForeignKey(p => p.AuthorId);

            modelBuilder.Entity<Author>()
                .HasMany(p => p.Books)
                .WithRequired(b => b.Author)
                .WillCascadeOnDelete(false);

            modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
        }

        public DbSet<Book> Books { get; set; }
        public DbSet<Author> Authors { get; set; }
    }

部分更新

  • 这是关于 0..1-To-Many 关系的问题
  • 我正在使用 .edmx。我刚刚了解到这完全否定了 OnModelCreating 方法。
  • 看来我可以在 DeleteConfirmed 方法中添加一个 Linq 语句来阻止它崩溃,但我真的不喜欢这种方法。
4

2 回答 2

0

如果我也在使用 fluent API,我一般不使用属性,所以这段代码将完全是约定和 fluent API。

您的帖子未指定,但经典书籍=>作者模型是多对多关系。您的实体代码似乎在说只有一位作者和一本书,而您流畅的代码似乎暗示有书籍和作者的集合。

FWIW,这就是我想要的:

public class Author
{
    public int AuthorId { get; set; }
    public string AuthorName { get; set; }

    public virtual ICollection<Book> Books { get; set; }
}

public class Book
{
    public int BookId { get; set; }
    public string BookName { get; set; }

    public virtual ICollection<Author> Authors { get; set; }
}

并在覆盖中:

  protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Author>()
            .HasMany(a => a.Books)
            .WithMany(b => b.Authors)
            .Map(m =>
                {
                    m.ToTable("AuthorBooks");
                    m.MapLeftKey("AuthorId");
                    m.MapRightKey("BookId");
                });
}

这将产生以下数据库:

在此处输入图像描述

我相信这就是获得级联所需的全部内容,按照惯例,它应该执行级联。

如果这不是您想要的,请发布。

塔尔

于 2012-08-20T19:16:02.660 回答
0

解决方案

在这个问题上苦苦挣扎了一天之后,我决定将一些自定义代码放入 DeleteConfirmed 方法中,以防止出现错误并提醒用户无法删除此记录。这可能不是处理这种情况的最佳方法,但它是有效的。

[HttpPost, ActionName("Delete")]
public ActionResult DeleteConfirmed(int id)
{
    Author author = db.Authors.Find(id);

    // Count # of Books for this Author
    int count = (from book in db.Books
                        where book.BookId == id
                        select book.BookId).Count();

    // Prevent deletion of this record has any associated records
    if (count> 0)
    {
        TempData["errors"] = "Bad user! You can't delete this record yet!";
        return RedirectToAction("Delete");
    }
    else
    {
        db.Categories.Remove(category);
        db.SaveChanges();
        return RedirectToAction("Index");
    }
}
于 2012-08-22T14:58:42.937 回答