EF6+SQL Server中newid()自动生成Id无法新增记录问题
解决EF6新增记录时SQL Server自定义默认值主键不生效的问题
问题场景
SQL Server中创建的表TableName,id列是varchar(10)类型的主键,设置了自定义默认值生成规则。通过SQL Server Management Studio手动新增记录时,id会自动生成;但使用EF6新增记录时,不指定Id值就会抛出错误:
The key field 'Id' cannot have a value of null. A non-null value is required for the key fields defined on type 'Booking'.
建表语句
CREATE TABLE [dbo].[TableName]( [id] [varchar](10) NOT NULL, [Price] [nvarchar](10) NULL, PRIMARY KEY CLUSTERED ( [id] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY] ) ON [PRIMARY] GO ALTER TABLE [dbo].[TableName] ADD DEFAULT (concat(left(newid(),(4)),'-',abs(checksum(newid()))%(10000))) FOR [id] GO
EF6新增代码
var db = new context(); var tableName = new TableName{ Price = "10" }; db.TableName.Add(tableName); db.SaveChanges();
解决方法
方法1:数据注解配置实体
在TableName实体类的Id属性上添加注解,明确告诉EF该主键由数据库生成:
public class TableName { [Key] [DatabaseGenerated(DatabaseGeneratedOption.Computed)] public string Id { get; set; } public string Price { get; set; } }
方法2:Fluent API配置
在DbContext的OnModelCreating方法中,通过Fluent API配置Id属性的生成规则:
protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Entity<TableName>() .Property(t => t.Id) .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Computed); }
方法3:手动生成主键值(不推荐)
如果不想修改EF配置,可以在代码中手动生成和数据库默认规则一致的Id值,再赋值给实体:
var newId = $"{Guid.NewGuid().ToString().Substring(0,4)}-{Math.Abs(Guid.NewGuid().GetHashCode()) % 10000}"; var tableName = new TableName{ Id = newId, Price = "10" }; db.TableName.Add(tableName); db.SaveChanges();
原因说明
EF6默认认为主键值需要由应用程序提供,即便数据库列设置了默认值,EF也不会主动跳过该列的赋值逻辑。只有通过配置DatabaseGeneratedOption.Computed,EF才会在插入记录时不传递Id值,让SQL Server使用预设的默认值生成规则。
内容的提问来源于stack exchange,提问作者EBRAHEM
相关产品推荐
相关产品推荐

