2011-07-18 2 views
6

J'écris une application ASP.net MVC3 en utilisant Entity Framework Code First et SqlCe4.Contrainte unique avec EFCodeFirst et SqlCe4

J'ai conçu plusieurs modèles, et j'en ai trouvé un qui s'avère intéressant. Voilà ce que j'ai jusqu'à présent:

public class Preference 
    { 
     public int PreferenceId { get; set; } 

     [Required] 
     public int StudentId { get; set; } 
     public virtual Student Student { get; set; } 

     [Required] 
     public int PresentationId { get; set; } 
     public virtual Presentation Presentation { get; set; } 

     [Required] 
     public int Rank { get; set; } 
    } 

Je cependant besoin d'une contrainte ou un index unique, parce que pour un élève en particulier, je veux qu'ils doivent avoir une liste de préférences, mais le PresentationId doit être unique pour chaque étudiant. Existe-t-il un moyen de le faire via Code First ou un attribut de validation? Cela ressemble à la descente d'une relation many-to-many avec l'objet Preference en tant qu'intermédiaire, pour ajouter la propriété Rank. Cependant, je n'arrive pas à trouver comment m'assurer que les valeurs sont uniques. Est-ce que la meilleure façon de vraiment ajouter manuellement un index unique à la base de données en dehors de EF?

Répondre

0

Voulez-vous profiter ce Eranga a dit, je fini par faire fonctionner de la même, mais comme celui-ci:

J'ai utilisé le code suivant dans ma classe DataContext:

public class StudentRegistrationContext : DbContext 
{ 
    public StudentRegistrationContext() 
    { 
     Database.SetInitializer(new StudentRegistrationDatabaseInitializer()); 
    } 

    public DbSet<Student> Students { get; set; } 
    public DbSet<Teacher> Teachers { get; set; } 
    public DbSet<Presenter> Presenters { get; set; } 
    public DbSet<Presentation> Presentations { get; set; } 
} 

Dans la base de données initialiseur de la classe, J'ai utilisé le suivant:

public class StudentRegistrationDatabaseInitializer : DropCreateDatabaseIfModelChanges<StudentRegistrationContext> 
{ 
    protected override void Seed(StudentRegistrationContext context) 
    { 
     base.Seed(context); 
     context.Database.ExecuteSqlCommand("CREATE UNIQUE INDEX UX_Preferences_StudentId_PresentationId ON Preferences (StudentId, PresentationId)"); 
    } 
} 
3

Actuellement (c'est-à-dire EF 4.1) EF n'a pas de mécanisme de configuration ou Attribute pour créer des index uniques.

Toutefois, si vous utilisez la base de données Initializer vous pouvez créer manuellement

public class MyInitializer : IDatabaseInitializer<MyContext> 
{ 
    public void InitializeDatabase(MyContext context) 
    { 
     if (!context.Database.Exists() || !context.Database.ModelMatchesDatabase()) 
     { 
      context.Database.DeleteIfExists(); 
      context.Database.Create(); 

      context.ObjectContext.ExecuteStoreCommand("CREATE INDEX IX_Preference_PresentationId ON Preference (PresentationId)"); 
     } 
    } 
} 

Ou l'exécuter en dehors du Initializer.

+0

j'utilisais actuellement la construction dans initialiseur: 'Database.SetInitializer (nouveaux DropCreateDatabaseIfModelChanges ());' Cependant, en essayant de mettre en œuvre votre solution, il ne parvient pas à compiler à la ligne contenant ModelMatchesDatabase() – mandreko

+1

Cette réponse a fonctionné pour moi et est dans ma version de production actuellement – Yablargo

1

Je ne suis pas sûr combien de temps la fonctionnalité a existé, mais dans EF5, vous pouvez utiliser la méthode CreateIndex et DropIndex dans vos méthodes Up() et Down(). Cela vous permet de créer des index uniques, qui fonctionnent presque de manière identique à des contraintes uniques, dans le propre langage d'EF.

public partial class UniqueIndexMigration 
{ 
    public override void Up() 
    { 
     // Create new unique index 
     this.CreateIndex("dbo.TableName", new[] { "Col1", "Col2", "Col3" }, true, "IX_TableName_Col1_Col2_Col3"); 
    } 

    public override void Down() 
    { 
     // Drop unique index 
     this.DropIndex("dbo.TableName", "IX_TableName_Col1_Col2_Col3"); 
    } 
} 

Le vrai, vu ci-dessus, est le paramètre qui spécifie qu'il s'agit d'une contrainte unique. Malheureusement, ces contraintes ne sont pas respectées lors de migrations ultérieures (EF ne les supprimera pas si vous modifiez le schéma sous-jacent), mais j'espère que grâce à l'API EF, votre code sera mis à niveau gratuitement lorsque cette fonctionnalité est finalement ajoutée.