2016-05-24 9 views
2

Ich versuche, einen nicht eindeutigen geclusterten Index für eine der Spalten hinzuzufügen, die von einem zusammengesetzten Schlüssel in einer Tabelle verwendet werden, die EF Code First verwendet. Bisher habe ich folgende Modelle. Beachten Sie das IX_PackageTargetPackageId Index-Attribut für die PackageTarget.PackageId Eigenschaft Ich versuche, hinzuzufügen:Entity Framework-Code Zuerst Clustered-Indizes und zusammengesetzte Schlüssel

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

Ich habe die folgende Migration, die für mich automatisch generiert wurde:

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

Die einzige Änderung Ich habe die Migration gemacht Fügen Sie clustered: false zu dem Primärschlüssel PackageTargets hinzu, da ich möchte, dass der IX_PackageTargetPackageId Index stattdessen gruppiert wird.

Nach der obigen Änderung, bin ich immer noch nicht in der Lage, die Migration laufen wie die folgende Ausnahme auftritt:

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

Aus meiner Migration, ich sind nicht andere gruppierte Indizes vorhanden sehen können. Fehle ich etwas?

Antwort

0

Sie sagte:

versucht, einen nicht-eindeutigen Clustered-Index

Und haben Sie dieses Attribut hinzufügen auf der PackageID Eigenschaft:

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

Sie haben aber auch die [Key] Attribut für mehrere Spalten definiert (da EF einen Primärschlüssel erfordert), Erstellen eines zusammengesetzten Primärschlüssels. Im EF-Code ist es zunächst nicht möglich, ohne einen Sprung durch einige Ringe einen nicht geclusterten Primärschlüssel zu definieren, so dass der zusammengesetzte Primärschlüssel immer auch der Clusterschlüssel ist.

Sie nicht zwei Clustered-Indizes auf einer Tabelle (siehe diese SO Artikel: What do Clustered and Non clustered index actually mean?) haben

Ein Clustered-Index physisch Nachbestellungen die Reihen auf der Platte auf dem Schlüssel basiert, während ein nicht gruppierten tut nicht physisch nachbestellen. Da es nicht möglich ist, die Zeilen gleichzeitig auf zwei verschiedene Arten zu ordnen, können Sie keine Clustered-Indizes angeben.

Sofern Sie keine Leistungstests durchgeführt haben und einen wirklichen Vorteil beim manuellen Festlegen des Clustering-Schlüssels sehen, empfehle ich, IsClustered auf "false" zu setzen und EF zu erlauben, den Clustering-Schlüssel zu verwalten.

0

Wie DVK Said. In Ihrem Fall versucht EF, zwei verschiedene Clustered-Indizes zu erstellen. Zuerst gruppiert für PK und zweitens für die Beschreibung in einem Indexattribut. Sie müssen PK nicht gruppieren. Leider in einer neuesten stabilen Version von EF 6 ist es nicht möglich oder nicht offensichtlich. Natürlich können Sie immer die Sql() - Methode der DbMigration mit reinem SQL verwenden. Aber diese Lösung sieht nicht elegant aus. Eine betta Version von EF 6.2 hat eine solche Möglichkeit.

Install-Package EntityFramework -Version 6.2.0-beta1 

Dann über fließende API haben Sie PK und Ihren Clustered-Index zu definieren. Dieses Beispiel von meinem Projekt.

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