ORMLite插入自增主键报错:无法插入显式值,如何解决?
解决自增主键插入失败的问题
这个报错的核心原因很明确:你的数据库map表的id是自增IDENTITY列,默认不允许手动插入值,但你的ORM在执行INSERT操作时,把Id字段的值也包含到SQL语句里了,这就触发了数据库的限制。下面是几种针对性的解决方法:
1. 给Id字段添加自增特性标记
首先要让ORM知道这个Id是数据库自动生成的,这样它就不会在插入时把Id字段放进SQL里。根据你用的ORM框架,选对应的特性:
如果用的是Dapper.Contrib
需要给Id字段加上[DatabaseGenerated(DatabaseGeneratedOption.Identity)]特性(记得引用System.ComponentModel.DataAnnotations.Schema命名空间):
[Schema("dbo")] [Alias("map")] public class Map { [PrimaryKey] [Alias("id")] [DatabaseGenerated(DatabaseGeneratedOption.Identity)] // 标记为数据库自增 public int Id { get; set; } [Alias("name")] public string Name { get; set; } // 其他字段 }
如果用的是ServiceStack.OrmLite
用OrmLite自带的[AutoIncrement]特性即可:
[Schema("dbo")] [Alias("map")] public class Map { [PrimaryKey] [AutoIncrement] // 标记为自增 [Alias("id")] public int Id { get; set; } [Alias("name")] public string Name { get; set; } // 其他字段 }
2. 确保插入前Id是默认值
创建新的Map对象时,不要手动给Id赋值(int类型默认就是0,保持这个状态就行),这样ORM就会自动忽略这个字段:
// 正确的新对象创建方式 var newMap = new Map { Name = "我的新地图", // 只给需要插入的字段赋值,不要碰Id }; // 执行插入,selectIdentity: true会返回生成的自增Id var generatedId = dbConnection.Insert<Map>(newMap, selectIdentity: true);
3. 手动编写INSERT语句(备选方案)
如果上面的方法不生效,你可以绕过ORM的自动生成,手动写SQL语句,只包含需要插入的字段:
var insertSql = @" INSERT INTO dbo.map (name /* 这里列出来其他需要插入的字段 */) VALUES (@Name /* 对应参数 */); SELECT SCOPE_IDENTITY();"; // 获取刚生成的自增Id var newId = dbConnection.QuerySingle<int>(insertSql, new { Name = newMap.Name, // 其他字段对应的参数 });
额外提醒
如果之前你不小心给新对象的Id赋了非0的值(比如从别的地方复制过来的对象),一定要把它重置为0,否则即使加了特性,有些ORM还是会把这个值传进去导致报错。
内容的提问来源于stack exchange,提问作者magicleon94
相关产品推荐
相关产品推荐

