如何用Dapper.Contrib+FluentMap更新含自定义名称标识列的实体?
问题根因
你使用的ORM(大概率是Dapper Extensions/Dapper Contrib/轻量级EF)执行更新操作时,默认将名为Id的主键属性映射到数据库id列作为更新条件,你配置的列映射规则未被ORM正确加载或者未关联主键规则,导致生成的SQL语句用了不存在的id列。
解决方案
方案1:直接用特性声明映射(适配绝大多数ORM,最简便)
在Id属性上同时添加[Column]特性指定数据库列名,自增主键额外添加[DatabaseGenerated]特性即可:
[Table("Business")] public class Business { [Key] [Column("BusinessId")] [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public int Id { get; set; } public string Name { get; set; } // 其余属性省略 }
配置完成后ORM执行_db.Update(business)时会自动将Id属性对应到BusinessId列生成更新条件,不会再报列不存在的错误。
方案2:修正Fluent API映射配置并加载
如果你更偏好Fluent API的映射方式(即你写的EntityMap类),需要完成两个配置:
- 在映射中明确标记
Id为主键,同时绑定列名:
public class BusinessMap : EntityMap<Business> { public BusinessMap() { Map(x => x.Id).ToColumn("BusinessId").Key(KeyType.Identity); } }
- 程序启动时注册映射类所在的程序集,让ORM可以扫描到你的映射规则:
// 以Dapper Extensions为例 DapperExtensions.DapperExtensions.SetMappingAssemblies(new[] { typeof(BusinessMap).Assembly });
方案3:全局配置主键命名规则(适合批量实体同规则场景)
如果你的项目中所有实体都遵循「属性名Id对应数据库表名+Id列」的规则,可以直接配置全局映射规则,无需每个实体单独配置:
// 自定义全局Mapper,以Dapper Extensions为例 public class CustomAutoMapper<T> : PluralizedAutoClassMapper<T> where T : class { public CustomAutoMapper() { var idProp = typeof(T).GetProperty("Id"); if (idProp != null) { Map(idProp).ToColumn($"{typeof(T).Name}Id").Key(KeyType.Identity); } } } // 程序启动时设置全局使用自定义Mapper DapperExtensions.DapperExtensions.DefaultMapper = typeof(CustomAutoMapper<>); DapperExtensions.DapperExtensions.SqlDialect = new SqlServerDialect();
配置完成后所有带Id属性的实体都会自动匹配对应表名+Id的数据库列,后续新增实体也不需要单独做主键映射。
内容的提问来源于stack exchange,提问作者Maccurt
相关产品推荐
相关产品推荐

