You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

EF6自动生成Author_Books1表名引发SaveChanges报错,求原因与解决

问题原因

你遇到的dbo.Author_Books1表不存在的问题,本质是EF6同时识别了两个多对多关系:

  1. 你在Author和Book实体中定义了双向集合导航属性(Author.Books和Book.Authors),EF6会默认将其识别为一个自动管理的多对多关系,并自动生成默认命名的中间表(规则是两个实体名按字母排序拼接,这里就是Author_Books,但因为你手动定义了同名的中间实体,EF会自动加后缀1避免冲突,所以变成了Author_Books1)。
  2. 你又手动定义了AuthorBook实体,并在DbSet中注册、配置了对应表Author_Books,EF将这视为另一个独立的关系。

两种关系冲突导致EF在保存时尝试访问自动生成的、实际不存在的Author_Books1表。

解决方法

你需要二选一:要么用EF自动管理的多对多,要么用手动定义的中间实体,不能混合使用。

方案一:使用EF自动管理的多对多关系(推荐,代码更简洁)

这种方式不需要手动定义中间实体,由EF自动维护中间表:

  1. 删除AuthorBook实体类。
  2. 删除AppDBContext中的public DbSet<AuthorBook> AuthorBooks{ get; set; }。
  3. 在OnModelCreating中配置多对多关系,指定中间表名和外键列名:
// 配置Author和Book的多对多关系
modelBuilder.Entity<Author>()
    .HasMany(a => a.Books)
    .WithMany(b => b.Authors)
    .Map(m =>
    {
        m.ToTable("Author_Books"); // 指定中间表名
        m.MapLeftKey("Author_AuthorId"); // 对应Author表的外键列名
        m.MapRightKey("Book_BookId"); // 对应Book表的外键列名
    });
  1. 关联作者和书籍的代码保持不变,但去掉不必要的db.Entry(newbook).State = System.Data.Entity.EntityState.Modified;(因为只是添加关联,没有修改书籍本身):
// Parse column for multiple possible books
if (worksheet.Cells[i, 3].Value != null)
{
    string[] possibleBooks = Regex.Split(worksheet.Cells[i, 3].Value.ToString(), ", ");

    foreach (string book in possibleBooks)
    {
         Book newbook = db.Books.Where(c => c.BookName == book).FirstOrDefault();
         if (newbook != null) // 避免空引用
         {
             Author.Books.Add(newbook);
         }
    }
 }

方案二:使用手动定义的中间实体(适合需要在中间表存储额外字段的场景)

如果需要在中间表添加更多字段(比如关联时间),可以用这种方式:

  1. 修改Author实体,将List<Book>改为List<AuthorBook>:
[Table("Authors")]
public class Author
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public Guid AuthorId{ get; set; }
    public string AuthorName{ get; set; }
    public List<AuthorBook> AuthorBooks { get; set; }
}
  1. 修改Book实体,将List<Author>改为List<AuthorBook>,同时修正Bookname的类型错误(原代码是Guid,应该是string):
[Table("Books")]
public class Book
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public Guid BookId{ get; set; }
    public string BookName{ get; set; } // 修正类型为string
    public List<AuthorBook> AuthorBooks { get; set; }
}
  1. 完善AuthorBook实体,添加外键对应的导航属性(可选但更规范):
[Table("Author_Books")]
public class AuthorBook
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public Guid AuthorBookId{ get; set; }
    public Guid Author_AuthorId{ get; set; }
    public Guid Book_BookId{ get; set; }

    // 添加导航属性,关联到Author和Book
    [ForeignKey("Author_AuthorId")]
    public Author Author { get; set; }

    [ForeignKey("Book_BookId")]
    public Book Book { get; set; }
}
  1. 在OnModelCreating中配置外键关系,替换原有的AuthorBook配置:
// 配置AuthorBook与Author的关联
modelBuilder.Entity<AuthorBook>()
    .HasRequired(ab => ab.Author)
    .WithMany(a => a.AuthorBooks)
    .HasForeignKey(ab => ab.Author_AuthorId);

// 配置AuthorBook与Book的关联
modelBuilder.Entity<AuthorBook>()
    .HasRequired(ab => ab.Book)
    .WithMany(b => b.AuthorBooks)
    .HasForeignKey(ab => ab.Book_BookId);

// 保留字段类型配置
modelBuilder.Entity<AuthorBook>().Property(p => p.AuthorBookId).HasColumnType("UniqueIdentifier").IsRequired();
modelBuilder.Entity<AuthorBook>().Property(p => p.Author_AuthorId).HasColumnType("UniqueIdentifier").IsRequired();
modelBuilder.Entity<AuthorBook>().Property(p => p.Book_BookId).HasColumnType("UniqueIdentifier").IsRequired();
  1. 修改关联作者和书籍的代码,创建AuthorBook实例添加到集合:
// Parse column for multiple possible books
if (worksheet.Cells[i, 3].Value != null)
{
    string[] possibleBooks = Regex.Split(worksheet.Cells[i, 3].Value.ToString(), ", ");

    foreach (string book in possibleBooks)
    {
         Book newbook = db.Books.Where(c => c.BookName == book).FirstOrDefault();
         if (newbook != null)
         {
             Author.AuthorBooks.Add(new AuthorBook 
             { 
                 Author_AuthorId = Author.AuthorId, 
                 Book_BookId = newbook.BookId 
             });
         }
    }
 }
额外注意事项
  • 原Book实体中的Bookname字段类型为Guid,这明显不符合业务逻辑(书籍名称是字符串),必须修正为string,否则无法匹配Excel中读取的书籍名称。
  • 保存作者时,不需要设置关联书籍的Modified状态,除非你确实修改了书籍的属性。

内容的提问来源于stack exchange,提问作者SalarianEngineer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 21:40:38