【问题标题】:Use an auto-generated UNIQUEIDENTIFIER that is NOT a part of the primary key使用不属于主键的自动生成的 UNIQUEIDENTIFIER
【发布时间】:2014-05-21 11:48:39
【问题描述】:

我有以下 EF 代码优先实体及其对应的配置:

public class Category
{
    public virtual long Id { get; set; }
    public Guid Guid { get; set; }
    public string Name { get; set; }
}

public class CategoryConfiguration:
    EntityTypeConfiguration<Category>
{
    public CategoryConfiguration ()
    {
        this.HasKey(entity => entity.Id);
        this.Property(entity => entity.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
        this.Property(entity => entity.Guid).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
    }
}

在字段Guid 上设置DatabaseGeneratedOption.Identity 选项似乎没有效果,SQL Server 中的相应表禁用了IDENTITY 选项。

有没有办法让 EF 中的 GUID/UNIQUEIDENTIFIER 列自动生成但同时又不是主键的一部分?

【问题讨论】:

  • IDENTITY 仅适用于数字数据类型(intdecimal,逗号后有 0 个数字)。它不能应用于uniqueidentifier
  • 你不能在实体的构造函数中做Guid.NewGuid()吗?当您创建一个全新的时,它会将 guid 设置为新的东西。当您加载现有实体时,它会将值设置为数据库中的任何内容。

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


【解决方案1】:

EF 不会“自动生成”与 ID 相关的任何内容,这一切都由数据库处理。 DatabaseGeneratedOption.Identity 也与主键无关,它只是向 EF 指示字段值是由数据库生成的,因此应该被拉下。

只要您的字段在数据库中的默认值设置为newid()newsequentialid(),那么DatabaseGeneratedOption.Identity 应该可以工作。

【讨论】:

    【解决方案2】:

    一个黑客...

    public calss Guid1 {
        public Guid Guid { get; set; }
    }
    
    public class Category {
        public virtual long Id { get; set; }
        public Guid1 Guid { get; set; }
        public string Name { get; set; }
    }
    
    public class CategoryConfiguration:EntityTypeConfiguration<Category> {
        public CategoryConfiguration () {
            HasKey(entity => entity.Id);
            Property(x => x.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
            HasReqired(x => x.Guid1);
        }
    }
    
    public class Guid1Configuration:EntityTypeConfiguration<Guid1> {
        public Guid1Configuration () {
            HasKey(x => x.Guid);
            Property(x => x.Guid).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
        }
    }
    

    这应该可以,但你会得到一个无用的表 Guid1。

    【讨论】:

      【解决方案3】:

      为了方便使用 EntityFramworkCore (.NET core) 的搜索者,您可以执行以下操作:

      EF 模型(注意创建时设置的默认值)

      public class Blog
          {
              public int BlogId { get; set; }
              public string Url { get; set; }
      
              public Guid BlogGuid { get; set; } = Guid.NewGuid();
      
              public List<Post> Posts { get; set; }
          }
      

      创建迁移,然后将默认更改为 defaultValueSql: "newid()":

      public partial class BlogGuidTest : Migration
          {
              protected override void Up(MigrationBuilder migrationBuilder)
              {
                  migrationBuilder.AddColumn<Guid>(
                      name: "BlogGuid",
                      table: "Blogs",
                      nullable: false,
                      defaultValueSql: "newid()");
      
                  // Add contraint to be safe
                  migrationBuilder.AddUniqueConstraint("BlogGuid_Unique", "Blogs", "BlogGuid");
              }
      
              protected override void Down(MigrationBuilder migrationBuilder)
              {
                  migrationBuilder.DropUniqueConstraint("BlogGuid_Unique", "Blogs");
      
                  migrationBuilder.DropColumn(
                      name: "BlogGuid",
                      table: "Blogs");
              }
          }
      

      然后更新数据库。

      对我来说似乎工作正常。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-12-21
        • 2023-04-01
        • 1970-01-01
        • 2011-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多