【问题标题】:How to configure EF Core 5 to make Guid keys generated by MS SQL Server database如何配置 EF Core 5 以使 MS SQL Server 数据库生成 Guid 密钥
【发布时间】:2021-05-13 04:49:56
【问题描述】:

我正在使用带有 SQL Server 的 EF Core 5,并且我有以下简单实体:

public class Person
{
    public Guid Id { get; set; }
    public string Name { get; set; }
}

在 DbContext 中添加为:

public DbSet<Person> People { get; set; }

我运行add-migration Person 得到以下生成的迁移代码:

public partial class Person : Migration
{
    protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.CreateTable(
            name: "People",
            columns: table => new
            {
                Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
                Name = table.Column<string>(type: "nvarchar(max)", nullable: true)
            },
            constraints: table =>
            {
                table.PrimaryKey("PK_People", x => x.Id);
            });
    }

    protected override void Down(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.DropTable(
            name: "People");
    }
}

然后我运行update-database 在数据库中创建这个Person 表。

  context.People.Add(new Person() { Name = "John" });
  context.SaveChanges();

查看 EF 日志,我看到执行了 SQL 命令:

  Executed DbCommand (21ms) [Parameters=[@p0='115b2a5d-56b7-42c8-2f42-08d8cd03a34e', @p1='John' (Size = 4000)], CommandType='Text', CommandTimeout='30']
  SET NOCOUNT ON;
  INSERT INTO [People] ([Id], [Name])
  VALUES (@p0, @p1);

我注意到 Id 的第一个参数是 @p0='115b2a5d-56b7-42c8-2f42-08d8cd03a34e',所以这意味着 Guid 是由 EF 生成的,而不是由数据库生成的。我希望它由数据库生成。

所以我在Id 属性中添加了以下属性:

public class Person
{
    [Key]
    [Required]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public Guid Id { get; set; }
    public string Name { get; set; }
}

但是当我创建一个新的迁移时,它给了我空的 Up()Down() 方法,这意味着从 EF 的角度来看,数据库中不应有任何更改。为什么是这样?以及如何让 EF Core 5 创建由数据库自动生成的 Id 主键。

【问题讨论】:

  • 迁移可能不会改变,但是日志中生成的SQL会改变吗?
  • Fluent API 选项适合您吗? stackoverflow.com/questions/25094711/…
  • 如果你这样做,使用这些属性,从一开始(擦除数据库并重新开始)它是否默认 NewID()?
  • @DavidG 刚刚查看了日志,并没有改变EF生成的SQL,所以参数@p0还是传给了数据库。
  • @madoxdev,我刚刚尝试过这样的 Fluent API:“modelBuilder.Entity().Property(x => x.Id).HasDefaultValueSql("NEWID()");"但下次我尝试添加新的Person 我得到SqlException: Cannot insert the value NULL into column 'Id', table 'dbo.People'; column does not allow nulls. UPDATE fails. The statement has been terminated.

标签: c# sql-server .net-core entity-framework-core


【解决方案1】:

我正在阅读 [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 行并找到了这个:

Entity Framework Core 不会实施价值生成策略。数据库提供程序在自动生成值的方式上有所不同。有些会为选定的数据类型生成值,例如 Identity、rowversion、GUI​​D。

如果您只想为您的 mssql 数据库生成一个复杂的密钥,那么我建议将 Id 的类型从 guid 更改为字符串

    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public string Id { get; set; }

在迁移文件中是这样的:

migrationBuilder.CreateTable(
columns: table => new
            {
                Id = table.Column<string>(type: "nvarchar(450)", nullable: false),
                Name = table.Column<string>(type: "nvarchar(max)", nullable: true)
            },

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-02
    • 1970-01-01
    • 1970-01-01
    • 2018-01-12
    相关资源
    最近更新 更多