Ich versuche, eine Basis DbContext zu schaffen, die alle gängigen Einheiten enthält, die immer in mehreren Projekten wiederverwendet werden, wie Seiten, Benutzer, Rollen, Navigation usw.EF Code zuerst: geerbt DbContext erstellt zwei Datenbanken
Dazu habe ich eine ContextBase-Klasse, die DbContext erbt und alle DbSets definiert, die ich möchte. Dann habe ich eine Context-Klasse, die ContextBase erbt, wo ich projektspezifische DbSets definiere. Die Klassen sind wie folgt definiert:
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
}
}
In meinem global.asax:
Database.SetInitializer(new MigrateDatabaseToLatestVersion<Context, Configuration>());
wo Konfiguration referes zu einer Klasse DbMigrationsConfiguration und Überschreiben der Seed-Methode vererben.
Die beiden Kontextklassen sind im selben Namespace definiert, aber Kreuzassemblierung (damit ich das Basisprojekt in mehreren vorhandenen Projekten aktualisieren kann, ohne den projektspezifischen Code zu berühren) - nicht sicher, ob dies relevant ist.
MEIN PROBLEM: Wenn dieser Code ausgeführt wird, es funktioniert gut, aber wenn sie in der Datenbank suchen, schafft es tatsächlich zwei verschiedene Datenbanken !! Eines enthält alle Basis-Entitätstabellen und eines enthält BEIDE Basis- und benutzerdefinierte Tabellen. CRUD-Operationen werden nur für die benutzerdefinierte Version ausgeführt (was offensichtlich das ist, was ich möchte), aber warum erstellt sie auch das Schema des anderen?
Jede Hilfe wird geschätzt, danke!
UPDATE:
Der folgende Code ist, was ich am Ende mit. Es ist nicht ideal, aber es funktioniert. Ich würde immer noch gerne Feedback zu Möglichkeiten bekommen, dies zu verbessern, aber in der Zwischenzeit hoffe ich, dass dies den Prozess weiter unterstützt. Ich kann es wirklich nicht empfehlen! Es ist extrem fehleranfällig und sehr frustrierend zu debuggen. Ich poste das nur, um zu sehen, ob es bessere Ideen oder Implementierungen gibt, um das zu erreichen.
Ein (aber nicht das einzige) Problem, das immer noch besteht, ist, dass die MVC-Ansichten manuell zu Projekten hinzugefügt werden müssen. Ich habe es dem Nuget-Paket hinzugefügt, aber es dauert 2 bis 3 Stunden, um ein Nuget-Paket mit so vielen Dateien anzuwenden, wenn VS mit TFS verbunden ist. Mit etwas mehr Arbeit und einer benutzerdefinierten View-Engine können die Ansichten vorkompiliert werden (http://blog.davidebbo.com/2011/06/precompile-your-mvc-views-using.html).
Die Lösung ist in die Base Framework-Projekte und die Custom-Projekte unterteilt (jede Kategorie enthält eigene Modelle und Repository-Muster). Die Framework-Projekte werden in einem Nuget-Paket verpackt und dann in beliebigen benutzerdefinierten Projekten installiert, sodass die allgemeine Funktionalität eines Projekts wie Benutzer-, Rollen- und Berechtigungsverwaltung, Inhaltsverwaltung usw. (oft als Boiler Plate bezeichnet) einfach hinzugefügt werden kann irgendwelche neuen Projekte. Auf diese Weise können Verbesserungen des Boilerplate in beliebigen vorhandenen benutzerdefinierten Projekten migriert werden.
Benutzerdefinierte Datenbank Initializer:
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);
}
}
}
}
Framework DB Migrationen Konfiguration:
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);
}
}
Benutzerdefinierte Project DB Migrationen Konfiguration:
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);
}
}
Der Brauch 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());
}
}
Rahmen 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);
}
Im global.asax AppStart:
//first remove the base context initialiser
Database.SetInitializer<ContextBase>(null);
//set the inherited context initializer
Database.SetInitializer(new MyMigrateDatabaseToLatestVersion());
Im 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>
Versuchen Sie, eine Verbindungszeichenfolge in der Basisklasse festzulegen (oder übergeben Sie sie vom übergeordneten Element), dh public ContextBase(): base ("MyConnection") –
Rufen Sie auch die Basis von ContextBase an? Was, wenn Sie mehr Konfigurationen hinzufügen, erstellt es eine Datenbank für jede Konfiguration? Versuchen Sie, die Konfigurationen hinzuzufügen und base.OnModelCreating aufzurufen. – MrFox
Erstellen Sie jemals direkt einen ContextBase-Kontext? ('new ContextBase()') Wenn Sie dies tun und nicht möchten, können Sie 'ContextBase'' abstract' machen, um sicherzustellen, dass der Compiler dies meldet. – hvd