La base de données est créée avec succès (comme le sont les tables) mais n'est pas amorcée. J'ai passé plusieurs heures et lu des tonnes d'articles mais je n'ai pas pu l'obtenir. Aucune suggestion?
Soit dit en passant, est-il possible d'appeler l'initialiseur sans avoir de référence à mon DatabaseContext dans le client?
J'ai inclus tout le code pertinent auquel je pouvais penser. Si quelque chose d'autre vous serait utile, faites-le moi savoir.
Choses que j'ai essayées:
Edit: La chose vraiment bizarre est que cela a fonctionné une fois, mais je ne sais pas comment ni pourquoi il s'est cassé à nouveau. J'assume des 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; }
}
Global.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>
Par souci de documentation, je partage ma solution ici. Parcourir tous les commentaires serait de toute façon une douleur. À la fin, j'avais DatabaseInitializer et DatabaseContext dans des classes distinctes. Je ne comprends pas vraiment pendant que ces petits changements le corrigeaient, mais le voici.
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
}
Global.asax.cs - Application_Start ()
protected void Application_Start()
{
Database.SetInitializer(new DatabaseInitializer());
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
}
Voici à quoi ressemblent toutes mes classes DbContext et elles se comportent très bien:
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 plusieurs fois et cela a très bien fonctionné pour moi.
Ma méthode Seed
n'a pas été invoquée même avec un appel correct à Database.SetInitializer
dans Application_Start
... La raison en était très simple: l'initialiseur ne peut pas être invoqué du tout si vous n'avez pas encore de code tilise en fait contexte de base de données.
Ceci est mon triste petit conte.
Premièrement, les leçons apprises:
Donc, pour éviter la tristesse:
Maintenant, la tristesse:
Tu peux appeler update-database
pour exécuter manuellement la méthode de départ dans la classe Configuration
. Cela nécessite enable-migrations
être également activé.
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" }
);
}
}
Le changement suivant dans le fichier Global.asax 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());
...
}
J'ai moi aussi eu du mal à invoquer Seed (). Et j'apprécie toutes les suggestions utiles ci-dessus et j'ai eu de la chance en utilisant DropCreateDatabaseAlways ... mais pas TOUJOURS !!
Plus récemment, j'ai ajouté la ligne de code suivante dans le constructeur de mon référentiel à bon escient:
public CatalogRepository()
{
_formCatalog.FormDescriptors.GetType();
}
Il suffisait de déclencher l'invocation de Seed (). Si vous avez tout essayé au-dessus de cette réponse et que vous n'avez toujours pas de chance, essayez-le. Bonne chance, c'était vraiment une expérience longue.
J'avais le même problème et après un changement dans les deux Global.asax
fichier et Intializer
fichier cela a fonctionné. J'espère que cela fonctionnera pour ceux qui ont encore des problèmes pour l'ensemencement des données.
Nouveau code dans Global.asax:
protected void Application_Start()
{
Database.SetInitializer<mycontextclassname>(new DropCreateDatabaseAlways<mycontextclassname>());
Database.SetInitializer(new Initializer());
...
}
code pour le fichier Intializer:
public class Initializer : System.Data.Entity.DropCreateDatabaseAlways<Context>
Je viens de rencontrer ce problème. J'ai supprimé la section "connectionstrings" du fichier Web.config, et actuellement l'application a commencé à fonctionner - sans la section connectionstrings! J'ajoute la section en arrière, et la base de données ne se réenserre pas. Ce n'est pas une bonne solution, mais j'ajoute simplement un point de données ici à ce qui peut potentiellement résoudre le problème.
Heureusement, c'est juste une petite application "jetable" que je vais bientôt jeter de toute façon ...
Assurez-vous méticuleusement que vous n'avez pas déclaré votre variable de contexte plus d'une fois. Si vous le déclarez à nouveau après l'ensemencement, la graine sera écrasée.
Mis à jour pour noter que cette réponse est incorrecte! La raison pour laquelle ma base de données n'a pas été semée reste un mystère (mais ce n'était pas l'absence d'un appel de constructeur de base par défaut, comme l'a noté @JaredReisinger)
J'apprécie que cette question soit un peu vieille mais je me suis retrouvée ici pour que quelqu'un d'autre puisse le faire. Voici ma valeur de tuppence:
Ma base de données était bien créée mais pas prédéfinie, même si j'ai supprimé la base de données et recommencé à utiliser DropDatabaseInitialiser.
Après avoir lu le code ci-dessus, j'ai remarqué que mon constructeur de contexte était ce
public MyApp_Context()
{
// some code
}
alors que l'exemple ci-dessus serait le suivant pour ma configuration
public MyApp_Context() : base("name=MyApp_Context")
{
// some code
}
Ouais, je n'appelais pas le constructeur de l'objet de base! Je ne m'attendais pas à ce que tout sauf l'ensemencement fonctionne dans ce cas, mais cela semble être le cas (répétable).
NB, je n'ai pas vraiment besoin de fournir le nom du contexte dans l'appel du constructeur de base; Je ne l'ai écrit que de cette façon au départ parce que je copiais le format de la solution ci-dessus. Donc, mon code est maintenant ceci, et l'amorçage fonctionne sur la création initiale de la base de données.
public MyApp_Context() : base()
{
// some code
}
L'événement de départ dans votre exemple ne sera déclenché qu'une seule fois lorsque vous utilisez DropCreateDatabaseIfModelChanges, vous pouvez le changer en DropCreateDatabaseAlways, je pense et il devrait déclencher l'événement de départ à chaque fois.
Modifier
Ceci est mon DataContext
public WebContext()
{
DbDatabase.SetInitializer(new DropCreateDatabaseIfModelChanges<WebContext>());
}
Cela m'est juste arrivé alors que je découvrais les fonctionnalités de Code First. Cette situation se produit souvent lorsque vous avez d'abord utilisé Code First pour générer votre base de données sans aucune stratégie d'initialisation.
Si vous décidez de le faire plus tard en implémentant une stratégie basée sur DropCreateDatabaseIfModelChanges
, mais sans modifier votre modèle, votre méthode Seed
ne sera pas appelée car la génération de la base de données et votre stratégie ne seront appliqué la prochaine fois que vous changez de modèle.
Si cela vous arrive, essayez de modifier un peu votre modèle pour tester cette hypothèse et je parie que votre base de données va être peuplée;)
Je n'ai pas encore la solution, sauf en utilisant une stratégie qui génère toujours la base de données, mais je ne suis vraiment pas à l'aise avec le fait de mettre la stratégie d'initialisation dans votre DbContext car cette classe est destinée à être utilisée dans votre environnement de production, Bien que la stratégie d'initialisation semble être principalement utilisée pour un environnement de développement fluide.