2016-05-24 4 views
2

EFのコードファーストアプローチを使用して、テーブル内の複合キーで使用される列の1つにクラスター化されていないインデックスを追加しようとしています。これまでのところ、私は以下のモデルを持っています。私が追加しようとしていますPackageTarget.PackageId性質上IX_PackageTargetPackageId index属性に注意してください。Entity Frameworkコードファーストクラスタードインデックスとコンポジットキー

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); 

のみ改正をIX_PackageTargetPackageIdインデックスをクラスタリングする代わりに、PackageTargetsプライマリキーにclustered: falseを追加します。

上記の改正後、私はまだ次の例外が発生したとして移行を実行することができません:

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)] 

しかし、あなたはまた、持っている:非ユニーク、クラスタ化インデックス

を追加してのPackageIDプロパティにこの属性を持つようにしようと

[Key]属性は複数の列に定義されています(EFには主キーが必要)ので、複合主キーが作成されます。 EFコードでは、最初に、クラスタ化されていないプライマリキーを定義することはできません(少なくともいくつかのフープを飛び越すことはできません)。そのため、コンポジットのプライマリキーは常にクラスタリングキーになります。

あなたがテーブルの上にクラスタ化インデックスを持つことができない(このSO記事参照:What do Clustered and Non clustered index actually mean?)を

キーに基づいてクラスタ化インデックスのディスク上に物理的に再受注行、非クラスタに対しん物理的には再注文しない。同時に2つの異なる方法で行を物理的に順序付けることはできないため、2つのクラスタード・インデックスを指定することはできません。

クラスタリング・キーを手動で指定することでパフォーマンス・テストを行っていない限り、IsClusteredをfalseに設定し、EFでクラスタリング・キーを管理することをお勧めします。

0

DVKとして。あなたの場合、EFは異なる2つのクラスタード・インデックスを作成しようとしています。最初にPK用にクラスター化され、インデックス属性でdescibed用にクラスター化されます。クラスタ化されていない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)); 
関連する問題