如何禁用EF Core外键列名自动生成 按原生列名绑定数据
问题原因
The required column 'MyStoreBookId' was not present in the results of a 'FromSql' operation
该报错由EF Core默认命名约定导致:当主实体类名为MyStoreBook,且声明了指向MyStoreBookTag的集合导航属性Tags时,EF会自动为关联的从实体生成外键列名MyStoreBookId,和你数据表实际存储的外键列名BookId不匹配,所以触发报错。
解决方案
你完全可以禁用自动生成的外键命名规则,手动指定和数据表原生列名匹配的映射规则,以下是几种常用方案:
方案1:属性名直接匹配(最简单)
直接将MyStoreBookTag类中的外键属性命名为和数据表列名完全一致的BookId,EF会自动按约定匹配,不会生成额外的默认列名:
public class MyStoreBookTag { public int Id { get; set; } // 外键属性名和表列名完全一致,自动匹配 public int BookId { get; set; } public string Name { get; set; } // 导航属性可按需添加 public MyStoreBook Book { get; set; } }
方案2:数据注解显式指定列名
如果不想修改原有实体属性名,可以用[Column]特性显式指定映射的数据库列名:
using System.ComponentModel.DataAnnotations.Schema; public class MyStoreBookTag { public int Id { get; set; } // 显式指定该属性映射的数据库列名为BookId [Column("BookId")] public int MyStoreBookId { get; set; } public string Name { get; set; } [ForeignKey(nameof(MyStoreBookId))] public MyStoreBook Book { get; set; } }
方案3:Fluent API配置(推荐,配置与实体解耦)
在DbContext的OnModelCreating方法中配置外键映射,完全自定义外键列名,不需要修改实体类代码:
protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<MyStoreBookTag>() .HasOne<MyStoreBook>() .WithMany(b => b.Tags) // 指定外键对应的数据库列名为BookId .HasForeignKey(bt => bt.BookId) // 可按需指定外键约束名和数据库现有约束保持一致 .HasConstraintName("FK_BookTags_Book_BookId"); }
如果需要全局禁用EF Core的默认外键命名约定,也可以在OnModelCreating中移除对应约定:modelBuilder.Conventions.Remove<ForeignKeyNamingConvention>();,但不推荐全局禁用,容易导致其他关联关系映射出错,优先针对单个关联手动配置即可。
临时解决方案(不推荐长期使用)
如果只是临时执行FromSqlRaw查询不想修改全局配置,可以在SQL语句中给列加别名匹配EF生成的默认列名:
var tags = dbContext.MyStoreBookTags .FromSqlRaw("select Id, Name, BookId as MyStoreBookId from BookTags where BookId = @bookid", new SqlParameter("@bookid", 你的参数值)) .ToList();
内容的提问来源于stack exchange,提问作者Teoman shipahi
相关产品推荐
相关产品推荐

