如何使用Entity Framework Core 2.1定义多字段索引?

3
我正在开发一个ASP.Net Core 2.1 API,并使用Entity Framework Core 2.1。我使用迁移来管理对数据库的更改。我的后端数据存储是Azure SQL Server的一个实例。
我需要在其中一个表上添加一个多字段非聚集索引,但是我在谷歌搜索中难以找到简明参考资料。
我尝试在POCO类中使用[Index()]数据注释,但它没有被识别。因此,我认为我必须在我的DbContext类的OnModelCreating方法中完成这个操作,但我还没有找到如何为多字段非聚集索引完成此操作的示例。
以下是一个实体类示例:
public class H1Record : EntityBase
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public long Id { get; set; }

    [ForeignKey("ShippingServicesFileId")]
    public ShippingServicesFile ShippingServicesFile { get; set; }

    [Required]
    public int ShippingServicesFileId { get; set; }

    [Column(TypeName = "varchar(20)")]
    public string BatchId { get; set; }

    [Column(TypeName = "varchar(34)")]
    [MaxLength(34)]
    public string ElectronicFileNumber { get; set; }

    [Column(TypeName = "varchar(1)")]
    [MaxLength(1)]
    public string ElectronicFileType { get; set; }

    [Column(TypeName = "varchar(8)")]
    [MaxLength(8)]
    public string DateOfMailing { get; set; }

    [Column(TypeName = "varchar(6)")]
    [MaxLength(6)]
    public string TimeOfMailing { get; set; }

    public DateTime MailingDateTime { get; set; }

    [Column(TypeName = "varchar(1)")]
    [MaxLength(1)]
    public string EntryFacilityType { get; set; }

    [Column(TypeName = "varchar(5)")]
    [MaxLength(5)]
    public string EntryFacilityZipCode { get; set; }

    [Column(TypeName = "varchar(4)")]
    [MaxLength(4)]
    public string EntryFacilityZipPlus4 { get; set; }

    [Column(TypeName = "varchar(2)")]
    [MaxLength(2)]
    public string DirectEntryOriginCountryCode { get; set; }

    [Column(TypeName = "varchar(3)")]
    [MaxLength(3)]
    public string ShipmentFeeCode { get; set; }

    [Column(TypeName = "varchar(6)")]
    [MaxLength(6)]
    public string ExtraFeeForShipment { get; set; }

    [Column(TypeName = "varchar(2)")]
    [MaxLength(2)]
    public string ContainerizationIndicator { get; set; }

    [Column(TypeName = "varchar(3)")]
    [MaxLength(3)]
    public string UspsElectronicFileVersionNumber { get; set; }

    [Column(TypeName = "varchar(12)")]
    [MaxLength(12)]
    public string TransactionId { get; set; }

    [Column(TypeName = "varchar(8)")]
    [MaxLength(8)]
    public string SoftwareVendorProductVersionNumber { get; set; }

    [Column(TypeName = "varchar(9)")]
    [MaxLength(9)]
    public string FileRecordCount { get; set; }

    [Column(TypeName = "varchar(9)")]
    [MaxLength(9)]
    public string MailerId { get; set; }

    public ICollection<D1Record> D1Records { get; set; } = new List<D1Record>();

    public ICollection<C1Record> C1Records { get; set; } = new List<C1Record>();

}

这里是实体基类(entitybase class)的代码:

public class EntityBase
{
    public DateTime CreatedDate { get; set; }
    public DateTime LastModifiedDate { get; set; }
    public int CreatedByUserId { get; set; }
    public int LastModifiedByUserId { get; set; }
    public bool DeleteFlag { get; set; }

}

我希望在我的DbContext的OnModelCreating方法中为ShippingServicesFileId和DeleteFlag创建一个非聚集索引,以便在运行Package Manager控制台中的add-migration时自动捕捉到它。你有什么想法吗?
2个回答

8

更新(适用于EF Core >= 5):

自EF Core 5.0以来,还可以使用数据注释在多个列上定义复合索引:

[Index(nameof([Column1]), nameof([Column2], ...))]
public class ...
{
    ...
}

使用

[Index(nameof([Column1]), nameof([Column2], ..., IsUnique = true))]

创建一个唯一的索引。

注意:无法使用数据注释(在SQL Server上的聚集索引)编写.ForSqlServerIsClustered()。在这里,您应该继续使用流畅API(见下文)。

请参见https://learn.microsoft.com/en-us/ef/core/modeling/indexes?tabs=data-annotations

更新(适用于EF Core<5):

您无法使用数据注释在多个列上创建索引,因此必须使用流畅API(在OnModelCreating中):

modeBuilder.Entity<ENTITYCLASS>().HasIndex(x => new {x.PROPERTY1, x.PROPERTY2, ...})

创建非聚集索引。使用.IsUnique()创建唯一索引。如果您想在SQL Server上创建聚集索引,请使用.ForSqlServerIsClustered()。可选地,您可以使用.HasName("...")为其命名。


1
这已经不再正确。根据微软的文档(https://learn.microsoft.com/en-us/ef/core/modeling/indexes?tabs=data-annotations),可以使用注释创建跨多个字段的复合索引。 - gwruck
1
这已经不再正确了。根据微软的文档(https://learn.microsoft.com/en-us/ef/core/modeling/indexes?tabs=data-annotations),可以使用注解来创建跨多个字段的复合索引。 - undefined
@gwruck我的回答是基于EF Core < 5和EF Core >= 5进行区分的。你有没有注意到这一点? - Grimm
1
...抱歉,我搞错了 - 可能是因为我有诵读障碍。我脑子里一直认为第二点与当前情况有关,但你提到的第一点对于大于等于5是正确的。 - gwruck
1
...抱歉,我的错 - 可能是我有诵读障碍。我脑海中认为第二点与当前情况有关,但你提出的第一点对于大于等于5是正确的。 - undefined
显示剩余3条评论

0

如果您喜欢这种方式,可以在迁移期间将列作为字符串数组传递。例如:

migrationBuilder.CreateIndex("IX_H1Record", "H1Record",new string[] { "ShippingServicesFileId", "DeleteFlag"}, "dbo");

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接