62 votes

Comment puis-je obtenir ma base de données à des semences à l'aide de Entity Framework CodeFirst?

La base de données est créée avec succès (comme le sont les tableaux), mais elle n'est pas amorcée. J'ai passé plusieurs heures et de lire des tonnes d'articles, mais n'ont pas été en mesure de l'obtenir. Toutes les suggestions?

Sur une note de côté, est-il possible d'appeler l'initialiseur, sans avoir une référence à mon DatabaseContext dans le client?

J'ai inclus tous les code que je pouvais penser. Si quoi que ce soit d'autre serait utile, s'il vous plaît laissez-moi savoir.

Les choses que j'ai Essayé:

  1. J'ai supprimé ma chaîne de connexion (car il est par défaut sqlexpress de toute façon, juste le nom a été changé)
  2. J'ai changé DropCreateDatabaseIfModelChanges à DropCreateDatabaseAlways, toujours le même.

Edit: vraiment étrange c'est que cela a fonctionné une fois, mais je n'ai aucune idée de comment ou pourquoi il a éclaté de nouveau. Je suis en supposant que les chaînes de connexion, mais qui sait.

DatabaseInitializer.cs

public class DatabaseInitializer : DropCreateDatabaseIfModelChanges<DatabaseContext>
{
  protected override void Seed(DatabaseContext context)
  {
    // Seeding data here
    context.SaveChanges();
  }
}

DatabaseContext.cs

public class DatabaseContext : DbContext
{
  protected override void OnModelCreating(DbModelBuilder mb)
  {
    // Random mapping code
  }

  public DbSet<Entity1> Entities1 { get; set; }
  public DbSet<Entity2> Entities2 { get; set; }

}

Mondiale.asax.cs - Application_Start()

protected void Application_Start()
{
  Database.SetInitializer<DatabaseContext>(new DatabaseInitializer());
  AreaRegistration.RegisterAllAreas();
  RegisterGlobalFilters(GlobalFilters.Filters);
  RegisterRoutes(RouteTable.Routes);
}

Client web.config

<connectionStrings>
  <add name="DatabaseContext" connectionString="data source=.\SQLEXPRESS;Database=Database;Integrated Security=SSPI;" providerName="System.Data.SqlClient" />
</connectionStrings>

SOLUTION

Pour l'amour de la documentation, je vais partager ma solution ici. La navigation de tous les commentaires serait une douleur, de toute façon. À la fin j'avais DatabaseInitializer et DatabaseContext dans des classes séparées. Je ne comprends pas vraiment tout ces petits changements fixe, mais ici il est.

DatabaseInitializer.cs

public class DatabaseInitializer : CreateDatabaseIfNotExists<DatabaseContext>
{
  protected override void Seed(DatabaseContext context)
  {
    // Seed code here
  }
}

DatabaseContext.cs

public class DatabaseContext : DbContext
{
  public DatabaseContext() : base("MyDatabase") { }

  protected override void OnModelCreating(DbModelBuilder mb)
  {
    // Code here
  }

  public DbSet<Entity> Entities { get; set; }
  // Other DbSets
}

Mondiale.asax.cs - Application_Start()

protected void Application_Start()
{
  Database.SetInitializer(new DatabaseInitializer());
  AreaRegistration.RegisterAllAreas();
  RegisterGlobalFilters(GlobalFilters.Filters);
  RegisterRoutes(RouteTable.Routes);
}

37voto

James D'Angelo Points 3099

C'est ce que mon DbContext classes ressemblent toutes et qu'ils semences parfaitement:

public class MyDbContext : DbContext
{
    public DbSet<MyClass> MyClasses { get; set; }

    protected override void OnModelCreating (DbModelBuilder modelBuilder)
    {
        base.OnModelCreating (modelBuilder);
        modelBuilder.Conventions.Remove<System.Data.Entity.ModelConfiguration.Conventions.PluralizingTableNameConvention> ();

        // Add any configuration or mapping stuff here
    }

    public void Seed (MyDbContext Context)
    {
        #if DEBUG
        // Create my debug (testing) objects here
        var TestMyClass = new MyClass () { ... };
        Context.MyClasses.Add (TestMyClass);
        #endif

        // Normal seeding goes here

        Context.SaveChanges ();
    }

    public class DropCreateIfChangeInitializer : DropCreateDatabaseIfModelChanges<MyDbContext>
    {
        protected override void Seed (MyDbContext context)
        {
            context.Seed (context);

            base.Seed (context);
        }
    }

    public class CreateInitializer : CreateDatabaseIfNotExists<MyDbContext>
    {
        protected override void Seed (MyDbContext context)
        {
            context.Seed (context);

            base.Seed (context);
        }
    }

    static MyDbContext ()
    {
        #if DEBUG
        Database.SetInitializer<MyDbContext> (new DropCreateIfChangeInitializer ());
        #else
        Database.SetInitializer<MyDbContext> (new CreateInitializer ());
        #endif
    }
}

J'ai utilisé ce modèle à quelques reprises et il a travaillé très bien pour moi.

10voto

user1068352 Points 336

Mon Seed méthode n'a pas été invoquée, même avec un bon appel à l' Database.SetInitializer en Application_Start... La raison pour laquelle il était très simple: initialiseur ne peut être invoquée à tout, si vous n'avez pas encore de code qui utilise le contexte de base de données.

9voto

Davious Points 380

Ceci est mon peu triste histoire.

Tout d'abord, les leçons apprises:

  1. La graine de la méthode ne sera pas appelé jusqu'à ce que le contexte est utilisé.
  2. Le Global.asax.cs ne sera pas touché un point d'arrêt sur la première exécution de colombie-britannique, il s'exécute avant le débogueur est attaché. Pour frapper un point d'arrêt sur Mondiale.asax.cs, vous pouvez ajouter un peu de blanc d'espace Web.config et appuyez sur une page; puis il va se faire frapper.
  3. Si il y a des VS connexions pour la db, le semis ne se produira pas. L'application renvoie une erreur.

Alors, pour éviter la tristesse:

  • Débranchez votre VS de connexion.
  • Commutateur de la classe de base DropCreateDatabaseAlways pour un aller.
  • Appuyez sur une page qui utilise le contexte.

Maintenant, la tristesse:

  1. J'ai eu mon personnalisée d'Initialiseur de classe dans mon Global.asax.cs fichier. J'ai eu un point de rupture sur mon Initialiseur de Graines de méthode; j'ai commencé l'application et la méthode ne l'ai jamais touché. :(
  2. - Je point un point de rupture dans ma Base de données.SetInitializer appel dans Application_Start. Qui n'a jamais touché. :(
  3. J'ai réalisé que je n'avais pas de db modifications de schéma, alors j'ai changé DropCreateDatabaseIfModelChanges à DropCreateDatabaseAlways. Pourtant, rien. :(
  4. Je suis finalement allé à une page qui utilise le contexte, et cela a fonctionné. :/

3voto

Despertar Points 5365

Vous pouvez appeler update-database d'exécuter manuellement la graine de méthode à l'intérieur de l' Configuration classe. Cela exige enable-migrations à être en marche.

PM> update-database
Specify the '-Verbose' flag to view the SQL statements being applied to the target database.
No pending code-based migrations.
Running Seed method.

internal sealed class Configuration : DbMigrationsConfiguration<ProjectManager.Data.Database.ProjectDb>
{
    public Configuration()
    {
        AutomaticMigrationsEnabled = false;
    }

    protected override void Seed(ProjectManager.Data.Database.ProjectDb context)
    {
        context.Status.AddOrUpdate(
            new Status() { Id = 1, Text = "New" },
            new Status() { Id = 2, Text = "Working" },
            new Status() { Id = 3, Text = "Completed" },
            new Status() { Id = 4, Text = "Skipped" }
        );
    }
}

2voto

Steven Burton Points 21

La modification suivante dans le Mondial.asax fichier a fonctionné pour moi:

Ancien Code:

    protected void Application_Start()
    {
        Database.SetInitializer<mycontextclassname>(new DropCreateDatabaseAlways<mycontextclassname>());             
       ...
    }

Nouveau Code:

    protected void Application_Start()
    {
        Database.SetInitializer<mycontextclassname>(new DropCreateDatabaseAlways<mycontextclassname>()); 
        Database.SetInitializer(new Initializer()); 
        ...
    }

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X