2016-05-24 93 views
2

我试图通过使用EF的Code First方法在一个表中的复合键使用的列的一个添加非唯一的聚簇索引。到目前为止,我有以下模型。注意在PackageTarget.PackageId财产IX_PackageTargetPackageId索引属性我想补充:实体框架代码首先,聚集索引和组合键

public class Package 
{ 
    [Key] 
    public int Id { get; set; } 
    [Required] 
    [Index("IX_PackageName", IsUnique = true)] 
    public string Name { get; set; } 
} 

public class Target 
{ 
    [Key] 
    public int Id { get; set; } 
    [Required] 
    public string Value { get; set; } 
} 

public class PackageTarget 
{ 
    [Key] 
    [Column(Order = 0)] 
    [Index("IX_PackageTargetPackageId", IsClustered = true)] 
    public int PackageId { get; set; } 

    [Key] 
    [Column(Order = 1)] 
    public int TargetId { get; set; } 

    [ForeignKey("PackageId")] 
    public virtual Package Package { get; set; } 

    [ForeignKey("TargetId")] 
    public virtual Target Target { get; set; } 
} 

我有自动为我生成以下迁移:

CreateTable(
    "dbo.PackageTargets", 
    c => new 
     { 
      PackageId = c.Int(nullable: false), 
      TargetId = c.Int(nullable: false), 
     }) 
    .PrimaryKey(t => new { t.PackageId, t.TargetId }) 
    .ForeignKey("dbo.Packages", t => t.PackageId, cascadeDelete: true) 
    .ForeignKey("dbo.Targets", t => t.TargetId, cascadeDelete: true) 
    .Index(t => t.PackageId, clustered: true, name: "IX_PackageTargetPackageId") 
    .Index(t => t.TargetId); 

CreateTable(
    "dbo.Packages", 
    c => new 
     { 
      Id = c.Int(nullable: false, identity: true), 
      Name = c.String(nullable: false) 
     }) 
    .PrimaryKey(t => t.Id) 
    .Index(t => t.Name, unique: true, name: "IX_PackageName"); 

CreateTable(
    "dbo.Targets", 
    c => new 
     { 
      Id = c.Int(nullable: false, identity: true), 
      Value = c.String(nullable: false) 
     }) 
    .PrimaryKey(t => t.Id); 

的唯一修正我对迁移做将clustered: false添加到PackageTargets主键,因为我希望将IX_PackageTargetPackageId索引改为集群。

上述修正案后,我仍然无法运行迁移为出现以下异常:

Cannot create more than one clustered index on table 'dbo.PackageTargets'. 
Drop the existing clustered index 'PK_dbo.PackageTargets' before creating another. 

从我的迁移,我看不到其他的聚集索引都存在。我错过了什么吗?

回答

0

你说:

尝试添加非唯一的聚簇索引

,并且对包标识属性此属性:

[Index("IX_PackageTargetPackageId", IsClustered = true)] 

但你也有[Key]属性定义在多个列上(因为EF需要一个主键),创建一个复合主键。首先在EF代码中,不可能(至少不要跳过一些箍环)定义一个非集群主键,所以你的复合主键也总是要成为集群键。

你不能在一个表上聚集索引(见SO文章:What do Clustered and Non clustered index actually mean?

聚簇索引的物理重新排序基于密钥磁盘上的行,而一个非聚集做不是在物理上重新排序。由于无法同时以两种不同方式对行进行物理排序,因此无法指定两个聚簇索引。

除非您已经完成了性能测试,并且看到了手动指定集群密钥的真正好处,否则我建议只将IsClustered设置为false并允许EF管理集群密钥。

0

正如DVK所说。在你的情况下,EF试图做两个不同的聚集索引。首先为PK进行聚类,然后在索引属性中对其进行聚类。你必须使不聚集的PK。 不幸的是,在EF 6的最新稳定版本中,它不可能或不明显。当然你可以使用纯SQL的DbMigration的Sql()方法。但是这个解决方案看起来不够优雅 EF 6.2的Betta版本有这种可能性。

Install-Package EntityFramework -Version 6.2.0-beta1 

然后通过流利的API你必须定义PK和你的聚集索引。这个考试来自我的项目。

modelBuilder.Entity<OrderWaybill>() 
    .HasKey(o => new { o.GUID, o.OrderDataCode } 
      , config => config.IsClustered(false)); 
modelBuilder.Entity<OrderWaybill>() 
    .HasIndex("IX_PRIMARY_SELECT", IndexOptions.Clustered 
       , ri=> ri.Property(x=>x.OrderDataCode) 
       , ri => ri.Property(x => x.Number));