代码之家  ›  专栏  ›  技术社区  ›  René Kåbis

Fluent Api未创建完全正确的迁移文件内容,因此未将唯一索引应用于数据库

  •  0
  • René Kåbis  · 技术社区  · 7 年前

    (标题已更改,有关更改,请参阅下面的编辑)

    当前项目:

    • DotNet 4.7
    • MSSQL Server 2012(最新)

    当我使用fluent API定义具有两个唯一索引的表时:

    Property(x => x.UserId)
      .HasColumnOrder(1)
      .HasColumnName("UserId")
      .HasColumnType("uniqueidentifier")
      .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity)
      .HasColumnAnnotation(
        "UserId", 
        new IndexAnnotation(
          new IndexAttribute("IX_UserId") { 
            IsUnique = true 
          }
        )
      )
      .IsRequired();
    Property(x => x.UserName)
      .HasColumnOrder(2)
      .HasColumnName("UserName")
      .HasColumnType("nvarchar")
      .HasMaxLength(256)
      .HasColumnAnnotation(
        "Username", 
        new IndexAnnotation(
          new IndexAttribute("IX_Username") { 
            IsUnique = true 
          }
        )
      )
      .IsRequired();
    

    在迁移文件中查看正确的迁移条目:

    UserId = c.Guid(
      nullable: false, 
      identity: true, 
      defaultValueSql: "NEWID()",
      annotations: new Dictionary<string, AnnotationValues> {
        { 
          "UserId", 
          new AnnotationValues(
            oldValue: null, 
            newValue: "IndexAnnotation: { 
              Name: IX_UserId, 
              IsUnique: True 
            }"
          ) 
        } 
      }
    ),
    UserName = c.String(
      nullable: false, 
      maxLength: 256, 
      annotations: new Dictionary<string, AnnotationValues> {
        { 
          "Username", 
          new AnnotationValues(
            oldValue: null, 
            newValue: "IndexAnnotation: { 
              Name: IX_Username, 
              IsUnique: True 
            }"
          ) 
        } 
      }
    ),
    

    然而,当我检查数据库并查看表的键/索引时,我注意到 UserId 索引为 已命名 IX_UserId PK_dbo.User ),并且不存在索引/唯一性 UserName 完全

    如中所示,虽然EF Fluent API能够创建看起来像是正确的迁移文件,并具有所有适当的属性,但这并不能转化为完全成功地迁移到DB,因为只需要创建默认索引(迁移文件中指定的所有索引信息都被完全忽略,以支持主键的默认装饰)。

    谁能解释一下我哪里出错了?


    编辑:

    嗯,我刚刚遇到 this other example ,也许这就是我错的地方?根据它,我的Fluent API应该是这样的:

    Property(x => x.UserId)
      .HasColumnOrder(1)
      .HasColumnName("UserId")
      .HasColumnType("uniqueidentifier")
      .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity)
      .HasColumnAnnotation(
        "UserId", 
        new IndexAnnotation(
          new IndexAttribute("IX_UserId") { 
            IsUnique = true,
            Order = 1
          }
        )
      )
      .IsRequired();
    Property(x => x.UserName)
      .HasColumnOrder(2)
      .HasColumnName("UserName")
      .HasColumnType("nvarchar")
      .HasMaxLength(256)
      .HasColumnAnnotation(
        "Username", 
        new IndexAnnotation(
          new IndexAttribute(),
          new IndexAttribute("IX_Username") { 
            IsUnique = true 
            Order = 2
          }
        )
      )
      .IsRequired();
    

    我是否正确阅读了另一篇文章?


    我刚刚发现正确的索引名 正在使用,但仅在这些键作为 外键 在其他表格中。所以无论在哪里 用户ID 作为外键存在于其他表中,它具有正确的索引名 IX_用户ID 即使我的Fluent API从未在该表中描述该外键的索引。

    威士忌酒探戈狐步舞。


    Fluent API是 不是 创建正确的迁移文件。只需将这些其他表的外键与迁移文件进行比较,这些其他表显然具有以下内容:

    .Index(t => t.UserId)
    .Index(t => t.CourseId);
    

    是的,Fluent-API没有构建正确的迁移文件,因为它缺少了一大堆迁移文件 .Index() 主键等的条目。

    1 回复  |  直到 7 年前
        1
  •  1
  •   Karel Tamayo    7 年前

    查看文档中的HasColumnAnnotation方法,它表示:

    Annotation name

    我猜想您没有使用有效的C#/EDM注释名称。尝试使用 IndexAnnotation.AnnotationName 常数作为索引的参数:

    using System.Data.Entity.Infrastructure.Annotations;
    
    ...
    
    Property(x => x.UserId)
        ...
        .HasColumnAnnotation(
             IndexAnnotation.AnnotationName, <-- this is the valid annotation name. 
              new ndexAttribute("Ix_UserId") {IsUnique = true});
    

    这是一个常数,等于 "Index"

    希望这有帮助!