2013-05-31 4 views
9

sagen, dass ich das folgende Modell haben:mit Entity Framework erstellen Datenbankindex

[Table("Record")] 
public class RecordModel 
{ 
    [Key] 
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)] 
    [Display(Name = "Record Id")] 
    public int RecordId { get; set; } 

    [StringLength(150)] 
    public string Name { get; set; } 

    [Required] 
    [StringLength(15)] 
    public string IMEI { get; set; } 
} 

Ist es möglich, einen Index der IMEI Spalte durch Verwendung eines Attributs, Datenaufbelichtung oder etwas aus dem Modell hinzufügen?

Antwort

11

Nach diesem Link: Creating Indexes via Data Annotations with Entity Framework 5.0 Sie irgendeine Art von Erweiterung Code schreiben sollte:

using System; 

[AttributeUsage(AttributeTargets.Property, Inherited = false, AllowMultiple = true)] 
public class IndexAttribute : Attribute 
{ 
    public IndexAttribute(string name, bool unique = false) 
    { 
     this.Name = name; 
     this.IsUnique = unique; 
    } 

    public string Name { get; private set; } 

    public bool IsUnique { get; private set; } 
} 

und die zweite Klasse:

using System.ComponentModel.DataAnnotations.Schema; 
using System.Data.Entity; 
using System.Linq; 
using System.Reflection; 

public class IndexInitializer<T> : IDatabaseInitializer<T> where T : DbContext 
{ 
    private const string CreateIndexQueryTemplate = "CREATE {unique} INDEX {indexName} ON {tableName} ({columnName})"; 

    public void InitializeDatabase(T context) 
    { 
     const BindingFlags PublicInstance = BindingFlags.Public | BindingFlags.Instance; 

     foreach (var dataSetProperty in typeof(T).GetProperties(PublicInstance).Where(
      p => p.PropertyType.Name == typeof(DbSet<>).Name)) 
     { 
      var entityType = dataSetProperty.PropertyType.GetGenericArguments().Single(); 

      TableAttribute[] tableAttributes = (TableAttribute[])entityType.GetCustomAttributes(typeof(TableAttribute), false); 

      foreach (var property in entityType.GetProperties(PublicInstance)) 
      { 
       IndexAttribute[] indexAttributes = (IndexAttribute[])property.GetCustomAttributes(typeof(IndexAttribute), false); 
       NotMappedAttribute[] notMappedAttributes = (NotMappedAttribute[])property.GetCustomAttributes(typeof(NotMappedAttribute), false); 
       if (indexAttributes.Length > 0 && notMappedAttributes.Length == 0) 
       { 
        ColumnAttribute[] columnAttributes = (ColumnAttribute[])property.GetCustomAttributes(typeof(ColumnAttribute), false); 

        foreach (var indexAttribute in indexAttributes) 
        { 
         string indexName = indexAttribute.Name; 
         string tableName = tableAttributes.Length != 0 ? tableAttributes[0].Name : dataSetProperty.Name; 
         string columnName = columnAttributes.Length != 0 ? columnAttributes[0].Name : property.Name; 
         string query = CreateIndexQueryTemplate.Replace("{indexName}", indexName) 
          .Replace("{tableName}", tableName) 
          .Replace("{columnName}", columnName) 
          .Replace("{unique}", indexAttribute.IsUnique ? "UNIQUE" : string.Empty); 

         context.Database.CreateIfNotExists(); 

         context.Database.ExecuteSqlCommand(query); 
        } 
       } 
      } 
     } 
    } 
} 

Nachdem Sie Ihre index auf diese Weise verwenden können:

[Required] 
[Index("IMEIIndex", unique: true)] 
[StringLength(15)] 
public string IMEI { get; set; } 
+0

Was müssen Sie verwenden, um 'Index' verwenden zu können? Wenn ich versuche, dieses '[Index (" IMEIIndex ", unique: true)]' es fragt mich, meine eigene Index-Klasse – Pete

+0

@Pete zu erstellen - aktualisiert meine Antwort - erste Version wurde nicht abgeschlossen. – MikroDel

+0

Sehr nett, scheint den Trick für mich getan zu haben. Vielen Dank! Ich gebe dir das Kopfgeld, wenn diese Seite mich lässt (ich muss anscheinend 1 Stunde warten) – Pete

14

UPDATE: Seit der Veröffentlichung von EF 6.1. (17. März 2014) gibt es tatsächlich ein [Index] Attribut verfügbar.

Funktionalität wie:

[Index("IMEIIndex", IsUnique = true)] 
public string IMEI { get; set; } 

kommt aus dem Kasten heraus.

PS: andere Eigenschaften sind Order und IsClustered.


Nach diesem Link: http://blogs.msdn.com/b/adonet/archive/2014/02/11/ef-6-1-0-beta-1-available.aspx

Es wird in EF 6.1 als Standard DataAnnotation Attribut zur Verfügung steht.

Mit IndexAttribute können Indizes angegeben werden, indem ein [Index] -Attribut für eine Eigenschaft (oder Eigenschaften) in Ihrem Code First-Modell platziert wird. Code First erstellt dann einen entsprechenden Index in der Datenbank.

+1

Danke. Nur eine Anmerkung: Sie müssen einen EntityFramework-Verweis in dem Projekt hinzufügen, in dem Sie dies verwenden möchten. Ein System.ComponentModel.DataAnnotations ist nicht genug. Nahm ein bisschen für mich, um herauszufinden. – Andrew

+2

Um fair zu sein, hat der aktuelle Zustand von EF 6.x "IsUnique = true/false" als zweiten Parameter. –

+0

@ClaudioLudovicoPanetta: guter Punkt, ich werde das beheben. – Stefan