2012-10-10 56 views
7

Estoy intentando crear un dbcontext base que contiene todas las entidades comunes que siempre va a ser reutilizados en múltiples proyectos, como páginas, usuarios, roles, etc. navegacióncódigo EF primera: dbcontext heredado crea dos bases de datos

Al hacerlo, tengo una clase ContextBase que hereda DbContext y define todos los DbSets que quiero. Luego tengo una clase Context que hereda ContextBase donde defino DbSets específicos del proyecto. Las clases se definen de la siguiente manera:

public class ContextBase : DbContext 
{ 
    public virtual DbSet<User> Users { get; set; } 
    //more sets 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     modelBuilder.Configurations.Add(new UsersConfiguration()); 
     //add more configurations 
    } 
} 


public class Context : ContextBase 
{ 
    public DbSet<Building> Buildings { get; set; } 
    //some more project specific sets 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     base.OnModelCreating(modelBuilder); 
     modelBuilder.Configurations.Add(new BuildingsConfiguration()); 
     //add more project specific configs 
    } 
} 

En mi global.asax:

Database.SetInitializer(new MigrateDatabaseToLatestVersion<Context, Configuration>()); 

donde referes de configuración a una clase que hereda DbMigrationsConfiguration y reemplazando el método de la semilla.

Las dos clases de contexto están definidas en el mismo espacio de nombres, pero el ensamblaje cruzado (para poder actualizar el proyecto base en múltiples proyectos existentes sin tocar el código específico del proyecto) - no estoy seguro si esto es relevante.

mi problema: Cuando se ejecuta este código, que funciona bien, pero cuando se busca en la base de datos, que en realidad crea dos bases de datos diferentes !! Uno que contiene todas las tablas de entidades base y otro que contiene AMBAS tablas base y personalizadas. Las operaciones CRUD solo se realizan en la versión personalizada (que obviamente es lo que quiero), pero ¿por qué crea el esquema del otro también?

¡Se agradece cualquier ayuda, gracias!

ACTUALIZACIÓN:

El código siguiente es lo que terminó con. No es ideal, pero funciona. Todavía me encantaría recibir comentarios sobre las formas de mejorar esto, pero mientras tanto espero que esto ayude a impulsar el proceso. ¡REALMENTE NO RECOMIENDO HACER ESTO! Es extremadamente propenso a errores y muy frustrante para depurar. Solo estoy publicando esto para ver si hay mejores ideas o implementaciones para lograr esto.

Uno de los problemas (aunque no el único) que aún existe es que las vistas de MVC deben agregarse manualmente a los proyectos. Lo he agregado al paquete Nuget, pero toma de 2 a 3 horas aplicar un paquete nuget con tantos archivos cuando VS está conectado a TFS. Con algo más de trabajo y un motor de vista personalizado, las vistas pueden precompilarse (http://blog.davidebbo.com/2011/06/precompile-your-mvc-views-using.html).

La solución se divide en los proyectos de Base Framework y los proyectos personalizados (cada categoría incluye sus propios modelos y patrones de repositorio). Los proyectos marco se empaquetan en un paquete Nuget y luego se instalan en proyectos personalizados que permiten agregar fácilmente la funcionalidad común de cualquier proyecto como usuario, rol y administración de permisos, administración de contenido, etc. (a menudo denominado placa de caldera). cualquier nuevo proyecto Esto permite que cualquier mejora de la plantilla repetitiva se migre en cualquier proyecto personalizado existente.

base de datos personalizada

inicializador:

public class MyMigrateDatabaseToLatestVersion : IDatabaseInitializer<Context> 
{ 
    public void InitializeDatabase(Context context) 
    { 
     //create the base migrator 
     var baseConfig = new FrameworkConfiguration(); 
     var migratorBase = new DbMigrator(baseConfig); 
     //create the custom migrator 
     var customConfig = new Configuration(); 
     var migratorCustom = new DbMigrator(customConfig); 

     //now I need to check what migrations have not yet been applied 
     //and then run them in the correct order 
     if (migratorBase.GetPendingMigrations().Count() > 0) 
     { 
      try 
      { 
       migratorBase.Update(); 
      } 
      catch (System.Data.Entity.Migrations.Infrastructure.AutomaticMigrationsDisabledException) 
      { 
       //if an error occured, the seed would not have run, so we run it again. 
       baseConfig.RunSeed(context); 
      } 
     } 
     if (migratorCustom.GetPendingMigrations().Count() > 0) 
     { 
      try 
      { 
       migratorCustom.Update(); 
      } 
      catch (System.Data.Entity.Migrations.Infrastructure.AutomaticMigrationsDisabledException) 
      { 
       //if an error occured, the seed would not have run, so we run it again. 
       customConfig.RunSeed(context); 
      } 
     } 
    } 
} 

DB migraciones de configuración del marco:

public class FrameworkConfiguration: DbMigrationsConfiguration<Repository.ContextBase> 
{ 
    public Configuration() 
    { 
     AutomaticMigrationsEnabled = false; 
    } 

    public void RunSeed(Repository.ContextBase context) 
    { 
     Seed(context); 
    } 

    protected override void Seed(Repository.ContextBase context) 
    { 
     // This method will be called at every app start so it should use the AddOrUpdate method rather than just Add. 

     FrameworkDatabaseSeed.Seed(context); 
    } 
} 

DB migraciones de configuración del proyecto de medida:

public class Configuration : DbMigrationsConfiguration<Repository.Context> 
{ 
    public Configuration() 
    { 
     AutomaticMigrationsEnabled = false; 
    } 

    public void RunSeed(Repository.Context context) 
    { 
     Seed(context); 
    } 

    protected override void Seed(Repository.Context context) 
    { 
     // This method will be called at every app start so it should use the AddOrUpdate method rather than just Add. 

     CustomDatabaseSeed.Seed(context); 
    } 
} 

La costumbre DbContext

//nothing special here, simply inherit ContextBase, IContext interface is purely for DI 
public class Context : ContextBase, IContext 
{ 
    //Add the custom DBsets, i.e. 
    public DbSet<Chart> Charts { get; set; } 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     base.OnModelCreating(modelBuilder); 

     //Assign the model configs, i.e. 
     modelBuilder.Configurations.Add(new ChartConfiguration()); 
    } 
} 

Marco DbContext:

//again nothing special 
public class ContextBase: DbContext 
{ 
    //example DbSet's 
    public virtual DbSet<Models.User> Users { get; set; } 
    protected override void OnModelCreating(DbModelBuilder modelBuilder); 
} 

En el AppStart global.asax:

 //first remove the base context initialiser 
     Database.SetInitializer<ContextBase>(null); 
     //set the inherited context initializer 
     Database.SetInitializer(new MyMigrateDatabaseToLatestVersion()); 

En el web.config:

<connectionStrings> 
    <!--put the exact same connection string twice here and name it the same as the base and overridden context. That way they point to the same database. --> 
    <add name="Context" connectionString="Data Source=.\SQLEXPRESS; Initial Catalog=CMS2013; Integrated Security=SSPI;MultipleActiveResultSets=true;" providerName="System.Data.SqlClient"/> 
    <add name="ContextBase" connectionString="Data Source=.\SQLEXPRESS; Initial Catalog=CMS2013; Integrated Security=SSPI;MultipleActiveResultSets=true;" providerName="System.Data.SqlClient"/> 
</connectionStrings> 
+0

Intenta establecer una cadena de conexión en la clase base (o pasarla de la matriz), es decir, ContextBase pública(): base ("MyConnection") –

+1

¿También estás llamando a la base de ContextBase? ¿Qué sucede si agrega más configuraciones, crea una base de datos para cada configuración? Intenta agregar las configuraciones y luego llama a base.OnModelCreating. – MrFox

+1

¿Alguna vez has creado un contexto 'ContextBase' directamente? ('new ContextBase()') Si lo hace, y no desea, puede hacer 'ContextBase'' abstract' para asegurarse de que los indicadores del compilador intenten hacerlo. – hvd

Respuesta

5

(a partir de los comentarios)

Estás creando ContextBase objetos directamente, al parecer como new T() en un método genérico con ContextBase como un argumento de tipo genérico, por lo que cualquier inicializadores para ContextBase también se ejecutan. Para evitar la creación de objetos ContextBase (si nunca se debe crear una instancia directamente, si el contexto derivado siempre se debe usar), puede marcar la clase como abstract.

3

Su ContextBase parece tener un inicializador, así .. Puedes eliminar esto por

Database.SetInitializer<ContextBase>(null); 
+0

Gracias, he encontrado la solución de acuerdo con el comentario de @hvd anterior, pero esta respuesta realmente me ayudó también. +1 – hofnarwillie

Cuestiones relacionadas