我有一个主键“Id”的实体,它是Guid:
public class FileStore
{
public Guid Id { get; set; }
public string Name { get; set; }
public string Path { get; set; }
}
还有一些配置:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<FileStore>().Property(x => x.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
base.OnModelCreating(modelBuilder);
}
当我尝试插入记录时,我收到以下错误:
无法将值NULL插入列'Id',表'FileStore';列不允许空值 . INSERT失败 . \ r \ n语句已终止 .
我不想手动生成Guid . 我只想插入一条记录并获取SQL Server生成的 Id
. 如果我设置 .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity)
, Id
列不是SQL Server中的Identity列 .
如何配置实体框架以在SQL Server中自动生成Guid?
10 回答
如果您执行Code-First并且已经拥有数据库:
你不能 . 你会/做很多事情 . 喜欢关系 . 哪个依赖于被拉回的数字,EF无法按照您设置的方式进行 . 打破每种模式的价格都有 .
在C#层中生成GUID,以便关系可以继续工作 .
这是什么东西?
除了将这些属性添加到您的Id列之外:
在您的迁移中,您应该更改
CreateTable
以将defaultValueSQL
属性添加到您的列中,即:这将使您无需手动触摸数据库,正如您在评论中指出的那样,您希望使用Code First避免使用该数据库 .
试试这个 :
你可以查看SO post .
您可以将数据库中Id的默认值设置为newsequentialid()或newid() . 然后EF的身份配置应该工作 .
它发生在我之前 .
当表已经创建并且我在
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity)
之后添加时,代码迁移在某种程度上无法为Guid列分配默认值 .修复:
我们只需要转到数据库,选择Id列并手动将
newsequentialid()
添加到Default Value or Binding
中 .无需更新dbo .__ MigrationHistory表 .
希望能帮助到你 .
添加
New Guid()
的解决方案通常不是首选,因为从理论上讲,您可能会意外地获得重复 .您不必担心在数据库中直接编辑 . 所有实体框架都是自动化我们数据库工作的一部分 .
翻译
成
如果我们的EF错过了一件事并且没有为我们添加默认值,那么请继续手动添加它 .
这适用于我(没有Azure),dev服务器上的SQL 2008 R2或本地工作站上的localdb \ mssqllocaldb . 注意:实体添加了Create,CreateBy,Modified,ModifiedBy和Version列 .
然后创建一个映射配置类
当您像这样执行add-migration时,这会在初始DbMigration中创建一个Up方法
Note: that the Id columns does not get a default value, don't worry
现在执行Update-Database,你最终应该在数据库中得到一个表定义,如下所示:
Note: we have a overridden the SqlServerMigrationSqlGenerator to ensure it does NOT make the Primary Key a Clustered index as we encourage our developers to set a better clustered index on tables
根据this,如果已经创建了表,则特定迁移不会检测到DatabaseGeneratedOption.Identity,这是我遇到的情况 . 所以我删除了数据库和特定的迁移并添加了新的迁移,最后更新了数据库,然后一切都按预期工作 . 我使用的是EF 6.1,SQL2014和VS2013 .
Entity Framework – Use a Guid as the primary key
使用Guid作为表的主键,在使用Entity Framework时,需要比使用整数时更省力 . 在您阅读/显示了如何操作之后,设置过程非常简单 .
Code First和Database First方法的过程略有不同 . 本文讨论了这两种技术 .
enter image description here
Code First
在采用代码第一种方法时使用Guid作为主键很简单 . 创建实体时,将DatabaseGenerated属性添加到主键属性中,如下所示;
实体框架将使用主键和uniqueidentifier数据类型按预期创建列 .
另请注意,非常重要的是,列上的默认值已设置为
(newsequentialid())
. 这会为每一行生成一个新的顺序(连续)Guid . 如果您如此倾向,可以将其更改为newid()
),这将导致每个新行的完全随机的Guid . 每次删除并重新创建数据库时都会清除此项,因此在采用Database First方法时这会更好 .Database First
数据库第一种方法遵循与代码第一种方法类似的方法,但您必须手动编辑模型才能使其正常工作 .
确保编辑主键列并在执行任何操作之前将(newsequentialid())或(newid())函数添加为默认值 .
enter image description here
接下来,打开你的EDMX图,选择合适的属性并打开属性窗口 . 确保StoreGeneratedPattern设置为identity .
无需在代码中为您的实体提供ID,在将实体提交到数据库后将自动填充该ID;
重要说明:您的Guid字段必须是主键,否则这不起作用 . 实体框架会给你一个相当神秘的错误信息!
Summary
Guid(全球唯一标识符)可以轻松地用作实体框架中的主键 . 根据您采取的方法,需要做一些额外的努力才能做到这一点 . 使用代码优先方法时,将DatabaseGenerated属性添加到关键字段 . 采用Database First方法时,在模型上明确将StoredGeneratedPattern设置为Identity .