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

Posted

技术标签:

【中文标题】Fluent Api 未创建完全正确的迁移文件内容,因此不会将唯一索引应用于数据库【英文标题】:Fluent Api is NOT creating a fully correct Migration file content, so that unique indexes are not being applied to the database 【发布时间】:2018-04-12 21:14:59 【问题描述】:

(标题已更改,请参阅下面的编辑以了解更改)

当前项目:

点网 4.7 MVC 5 C# 7.1 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();

am在迁移文件中看到了正确的迁移条目:

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 不存在索引/唯一性根本。我需要在 SQL Management Studio 中手动创建它。

虽然 EF Fluent API 能够创建看起来像正确的迁移文件,并包含所有适当的属性,但这并没有转化为完全成功迁移到数据库,因为仅需要创建默认索引 (迁移文件中指定的所有索引信息都被完全忽略,有利于主键的默认装饰)。

谁能解释我哪里出错了?


编辑:

嗯……刚刚遇到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();

我是否正确阅读了其他帖子?


编辑 2:

Uhhhh... 我刚刚发现 使用了正确的索引名称,但仅在这些键作为 外键 存在于其他表中的位置上。因此,无论UserId 作为外键存在于其他表中,它都有正确的索引名称IX_UserId,即使我的 Fluent API 从未在该表中描述该外键的索引。

威士忌。探戈。狐步舞。


编辑 3:

Fluent API没有创建正确的迁移文件。刚刚将那些其他表的外键与迁移文件进行了比较,那些其他表显然有以下内容:

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

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

【问题讨论】:

【参考方案1】:

查看 HasColumnAnnotation 方法的文档:

我的猜测是您没有使用有效的 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" 的常量值,但我怀疑这可能是您的问题的原因。

希望这会有所帮助!

【讨论】:

以上是关于Fluent Api 未创建完全正确的迁移文件内容,因此不会将唯一索引应用于数据库的主要内容,如果未能解决你的问题,请参考以下文章

QuickBlox - 如何使用 REST API + PHP 创建 blob 内容

流体力学模拟软件fluent,使用Gambit创建网格后无法导出网格文件

使用 Entity Framework 6.1 fluent API 创建唯一索引

EF Core Fluent API

如何在 EF Core 中通过 Fluent Api 创建加密列

EF6:创建存储过程。使用 Fluent API 或 DBMigrations?