C# EF Code First-具有导航属性的多列索引

C# EF Code First-具有导航属性的多列索引,c#,entity-framework,ef-code-first,entity-framework-migrations,ef-fluent-api,C#,Entity Framework,Ef Code First,Entity Framework Migrations,Ef Fluent Api,我想在多个列上放置索引(如中所述),但其中一个属性是导航属性,模型中没有外键属性 TL;DR位于底部 我的模型: public class User { public int Id { get; set; } public string Email { get; set; } public virtual Shop Shop { get; set; } } public class Shop { public int Id { get; set; }

我想在多个列上放置索引(如中所述),但其中一个属性是导航属性,模型中没有外键属性

TL;DR位于底部


我的模型:

public class User
{
    public int Id { get; set; }
    public string Email { get; set; }
    public virtual Shop Shop { get; set; }
}

public class Shop
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public class Context : DbContext
{
    public DbSet<User> Users { get; set; }
    public DbSet<Shop> Shops { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<User>().HasRequired(u => u.Shop).WithMany();
        modelBuilder.Entity<User>().Property(u => u.Email).HasMaxLength(256);
    }
}
我希望创建一个索引,如下所示:

modelBuilder.Entity<User>().Property(x => x.Email).AddMultiColumnIndex("UX_User_EmailShopId", 0, unique: true);
modelBuilder.Entity<User>().Property(x => x.Shop.Id).AddMultiColumnIndex("UX_User_EmailShopId", 1, unique: true);

要使用C#和流畅的语法实现这一点,您必须做几件事

  • 将ShopId(外键)添加到用户类。EF将理解这是Shop navigation属性的外键,因此无需执行更多操作

    public virtual Shop Shop { get; set; }
    public int ShopId { get; set; }
    
  • 在modelbuilder索引配置中使用x.ShopId

    modelBuilder.Entity<User>().Property(x => x.ShopId).AddMultiColumnIndex("UX_User_EmailShopId", 1, unique: true);
    
    或者使用迁移,并且不希望将“FK”属性ShopId添加到用户类中,您可以在migration UP方法中添加索引创建

    CreateIndex("Users", new[] { "Email", "ShopId" }, true, "UX_User_EmailShopId");
    

    如果模型中没有定义shop_id,则无法使用fluent api执行此操作

    如果您注意到了,您使用的是DbModelBuilder,它是指模型,即在您的代码中“定义”的模型。fluent API只有一种方式,从代码到数据库,但不是相反

    您仍然可以创建索引,而无需向模型中添加shop_id,但可以使用纯SQL,而不是fluent API

    您可以使用注释来完成它。您的用户类需要类似,但只能使用EF 6.1

    public class User
    {
        [Index("UX_User_EmailShopId", 1, IsUnique =  true)]
        public int Id { get; set; }
    
        [Index("UX_User_EmailShopId", 2, IsUnique = true)]
        public string Email { get; set; }
    
        [Index("UX_User_EmailShopId", 3, IsUnique = true)]
        public int ShopId { get; set; }
    
        [ForeignKey("ShopId")]
        public virtual Shop Shop { get; set; }
    }
    

    TL&DR:如果希望在FLUENT模式中有多个索引,可以执行以下操作:

    You can now (EF core 2.1) use the fluent API as follows:
    
    modelBuilder.Entity<ClassName>()
                .HasIndex(a => new { a.Column1, a.Column2});
    
    您现在可以(EF core 2.1)使用fluent API,如下所示:
    modelBuilder.Entity()
    .HasIndex(a=>new{a.Column1,a.Column2});
    
    我确实忘记提到了
    HasmaxLength
    ,但我的模型中确实有它。但我问题的重点是如何在没有外键属性
    int Shopid
    的情况下实现它。你的答案与我给出的链接问题中的答案几乎相同。重点是在没有键属性的情况下实现它。显然没有阅读你的问题已经足够好了。如果使用迁移而不向模型中添加ShopId属性,则添加了另一种选择。我希望使用fluent api,而不是在模型中添加ShopId属性。因此没有乐趣。
    modelBuilder.Entity<User>().Property(c => c.Email).HasMaxLength(255).AddMultiColumnIndex("UX_User_EmailShopId", 0, unique: true);;
    
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<User>().HasRequired(u => u.Shop).WithMany();
        modelBuilder.Entity<User>().Property(x => x.Email).HasMaxLength(255).AddMultiColumnIndex("UX_User_EmailShopId", 0, unique: true);
        modelBuilder.Entity<User>().Property(x => x.ShopId).AddMultiColumnIndex("UX_User_EmailShopId", 1, unique: true);
    }
    
    CREATE UNIQUE NONCLUSTERED INDEX [UX_User_EmailShopId]
    ON [dbo].[Users]([Email] ASC, [ShopId] ASC);
    
    CreateIndex("Users", new[] { "Email", "ShopId" }, true, "UX_User_EmailShopId");
    
    public class User
    {
        [Index("UX_User_EmailShopId", 1, IsUnique =  true)]
        public int Id { get; set; }
    
        [Index("UX_User_EmailShopId", 2, IsUnique = true)]
        public string Email { get; set; }
    
        [Index("UX_User_EmailShopId", 3, IsUnique = true)]
        public int ShopId { get; set; }
    
        [ForeignKey("ShopId")]
        public virtual Shop Shop { get; set; }
    }
    
    You can now (EF core 2.1) use the fluent API as follows:
    
    modelBuilder.Entity<ClassName>()
                .HasIndex(a => new { a.Column1, a.Column2});