使用.EDMX在MVC中定义FK关系

时间:2012-08-20 18:53:08

标签: c# asp.net-mvc entity-framework foreign-keys asp.net-mvc-4

我只是在使用MVC 4并且在我的应用程序中遇到错误,我需要一些修复帮助。

我有一个作者&书桌。 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方法。
  • 看来我可以将Linq语句放入DeleteConfirmed方法来阻止它崩溃,但我真的不喜欢这种方法。

2 个答案:

答案 0 :(得分:0)

如果我也使用了流畅的API,我通常不会使用这些属性,所以这段代码将完全是常规和流畅的API。

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

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");
                });
}

这将产生db:

enter image description here

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

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

塔尔

答案 1 :(得分: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");
    }
}