2016-05-24 151 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));