51 votos

¿Cómo puedo obtener mi base de datos a la semilla utilizando Entity Framework CodeFirst?

La base de datos se ha creado correctamente (como son las tablas), pero no es cabeza de serie. He pasado varias horas y leer toneladas de artículos, pero no ha sido capaz de llegar. Alguna sugerencia?

En una nota de lado, es posible llamar a la inicializador sin tener una referencia para mi DatabaseContext en el cliente?

He incluido todo el código correspondiente en el que podía pensar. Si cualquier otra cosa sería útil, por favor hágamelo saber.

Cosas que he Probado:

  1. He eliminado mi cadena de conexión (ya que por defecto sqlexpress de todos modos, sólo se cambió el nombre)
  2. He cambiado DropCreateDatabaseIfModelChanges a DropCreateDatabaseAlways, que sigue siendo el mismo.

Edit: La cosa realmente extraña es que funcionó una vez, pero no tengo idea de cómo o por qué se rompió de nuevo. Estoy asumiendo que las cadenas de conexión, pero quién sabe.

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

Cliente web.config

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

SOLUCIÓN

Por el bien de la documentación, estoy compartiendo mi solución aquí. Navegar por todos los comentarios que iba a ser un dolor de cabeza de todos modos. Al final he tenido DatabaseInitializer y DatabaseContext en clases separadas. Yo no entiendo realmente, mientras que estos pequeños cambios fijos, pero aquí 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
}

Global.asax.cs - Application_Start()

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

29voto

James D'Angelo Puntos 3099

Esto es lo que mi DbContext clases todos se parecen y que la semilla de 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
    }
}

He utilizado este patrón un par de veces y ha funcionado muy bien para mí.

8voto

user1068352 Puntos 336

Mi Seed método no fue invocada, incluso con la llamada correcta a Database.SetInitializer en Application_Start... La razón era muy simple: inicializador, no puede ser invocada en todo, si usted todavía no tiene ningún código que utiliza la base de datos de contexto.

6voto

Davious Puntos 380

Esta es mi triste historia.

En primer lugar, las lecciones aprendidas:

  1. La semilla método no será llamado hasta que el contexto se utiliza.
  2. El Global.asax.cs no golpear un breakpoint en la primera ejecución bc se ejecuta antes de que el depurador se adjunta. Golpear a un breakpoint en Global.asax.cs, usted tiene puede agregar un poco de espacio en blanco a la Web.config y presione una página; a continuación, va a recibir un golpe.
  3. Si hay VS conexiones a la base de datos, la siembra no va a suceder. La aplicación va a tirar un error.

Por tanto, para evitar la tristeza:

  • Desconecte el VS de conexión.
  • Interruptor de la clase base DropCreateDatabaseAlways para uno ir.
  • Presione una página que utiliza el contexto.

Ahora, la tristeza:

  1. Yo tenía mi costumbre de Inicializador de la clase en mi Mundial.asax.cs archivo. Yo tenía un punto de quiebre en mi Inicializador de Semillas método; empecé la aplicación y el método nunca fue golpeado. :(
  2. Me punto a a un punto de quiebre en mi Base de datos.SetInitializer llamada en el Application_Start. Que nunca llegó a golpear. :(
  3. Me di cuenta de que yo no tenía ningún db de los cambios de esquema, así que he cambiado DropCreateDatabaseIfModelChanges a DropCreateDatabaseAlways. Aún así, nada. :(
  4. Finalmente fui a una página que utiliza el contexto, y funcionó. :/

2voto

Steven Burton Puntos 21

El siguiente cambio en el Global.archivo asax trabajado para mí:

Código Antiguo:

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

Nuevo Código:

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

1voto

Joe Puntos 11

Yo también he tenido dificultades para conseguir Semilla() se invoca. Y agradezco todas las sugerencias anteriores y he tenido la suerte de usar DropCreateDatabaseAlways ... ¡pero no SIEMPRE!!

Más recientemente, he añadido la siguiente línea de código en el constructor de mi Repositorio a buen efecto:

    public CatalogRepository()
    {
        _formCatalog.FormDescriptors.GetType();

    }

Fue suficiente para desencadenar la Semilla() siendo invocado. Si usted ha intentado todo por encima de esta respuesta y no ha habido suerte, darle una oportunidad. Buena suerte esta fue realmente una pérdida de tiempo de la experiencia.

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X