I created a web starter application with VS 2015 ctp, and I would like to add an in-memory store to do some test, but when I try to read the data, I get this message
The data stores 'SqlServerDataStore' 'InMemoryDataStore' are
available. A context can only be configured to use a single data
store. Configure a data store by overriding OnConfiguring in your
DbContext class or in the AddDbContext method when setting up
services.
How can I do to create a second datastore? Now I have this row in the ConfigureService method
AddEntityFramework(Configuration)
.AddSqlServer()
.AddDbContext<ApplicationDbContext>()
.AddInMemoryStore()
.AddDbContext<WorkModel>( options => { options.UseInMemoryStore(persist: true); });
Edit:
Looks like the scenario is not clear.
I have the identy sql server dbcontext, and I want to add a second dbcontext, totally separated, that I want to run in memory. I'm looking how configure two different dbcontext, in this case using two different datastores.
The first one is the Identity ApplicationDbContext, and another is something like this:
public class WorkModel : DbContext
{
public DbSet<Cliente> Clienti { get; set; }
public DbSet<Commessa> Commesse { get; set; }
protected override void OnModelCreating(ModelBuilder builder) {
builder.Entity<Cliente>().Key(cli => cli.ClienteId);
builder.Entity<Commessa>().Key(cli => cli.CommessaId);
}
}
Or whatever custom dbcontext do you like
It's possible use one DbContext type with multiple data stores. It won't however play well with your calls to .AddDbContext(). Here is an example of how to do it taking .ConfigureServices() entirely out of the picture.
class MyContext : DbContext
{
bool _useInMemory;
public MyContext(bool useInMemory)
{
_useInMemory = useInMemory;
}
protected override void OnConfiguring(DbContextOptions options)
{
if (_useInMemory)
{
options.UseInMemoryStore(persist: true);
}
else
{
options.UseSqlServer();
}
}
}
You can then instantiate your context specifying which provider to use.
var inMemoryContext = new MyContext(useInMemory: true);
var sqlServerContext = new MyContext(useInMemory: false);
You probably need to do something like this instead...
// Add first DbContext here
AddEntityFramework(Configuration)
.AddSqlServer()
.AddDbContext<ApplicationDbContext>();
// Add second DbContext here
AddEntityFramework(Configuration)
.AddInMemoryStore()
.AddDbContext<WorkModel>(options => { options.UseInMemoryStore(persist: true); });
In my case, when I needed to create two SQL Contexts, I had to do this...
AddEntityFramework(Configuration)
.AddSqlServer()
.AddDbContext<ApplicationDbContext>()
.AddDbContext<AnotherDbContext>();
In my case, I'm using Entity Framework Core 1.0.1 with ASP.NET Core 1.0.1 and I want to run the same project on Windows and OS X but with different databases. So this is working for me:
Added some logic in Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("WindowsConnection")));
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlite(Configuration.GetConnectionString("OSXConnection")));
}
}
Then defined the two different connection strings in appsettings.json:
"ConnectionStrings":
{
"WindowsConnection": "Server=(localdb)\\mssqllocaldb;Database=aspnet-{dbname}-{dbguid};Trusted_Connection=True;MultipleActiveResultSets=true",
"OSXConnection": "Data Source=\/Users\/{username}\/Documents\/{projectname}\/bin\/debug\/netcoreapp1.0\/{dbname}.db"
}
And added this logic to ApplicationDbContext.cs:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
optionsBuilder.UseSqlite("Filename=./{dbname}.db");
}
}
If you're dbcontext has
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
#warning To protect potentially sensitive information in your connection string, you should move it out of source code. See http://go.microsoft.com/fwlink/?LinkId=723263 for guidance on storing connection strings.
optionsBuilder.UseSqlServer(<connection string>);
}
then you can avoid the double configuration by adding a guard
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if(!optionsBuilder.IsConfigured){
#warning To protect potentially sensitive information in your connection string, you should move it out of source code. See http://go.microsoft.com/fwlink/?LinkId=723263 for guidance on storing connection strings.
optionsBuilder.UseSqlServer(<connection string>);
}
}
and then have a class that extends your DBContext which uses the inmemory provider, and you instantiate explicitly for your tests. Then you can pass in to the target classes, and avoid the double provider issue.
Related
EDIT: I also have a completely different approach where I have just about all of that crap commented out. I am able to call into my method and I configured the connect string to connect to the server, but not to the database. Then I want to connect to the different database depending on some data passed in (like the database name maybe?). Is there a way to call OnConfiguring on the fly so I can configure my connection string to be different each time I call my method?
I know some of you are going to look at this and roll your eyes with my stupidity, but we all had to start somewhere! I have a scenario with one database server but multiple databases all which share the same schema. Currently I am rewriting code for each database and it is a mess, so I am trying to clear it up. I have gotten myself pretty confused here so I am looking for advice from some of you gurus out there. I am a beginner here and trying to do something I find very advanced here so go easy on me. I will keep my examples with just two databases, but really there are 10+ databases that are all the same that I need to switch between often. My goal is to try to get rid of this 1, 2, 3, 4, 9, 10, etc stuff all over the place when I want to save or access a record, and have one thing controlling it all.
I created a base class for my database context
public partial class opkDataBaseContext : DbContext
{
private DbContextOptions<opkData1Context> options1;
private DbContextOptions<opkData2Context> options2;
public opkDataBaseContext()
{
}
public opkDataBaseContext(DbContextOptions<opkDataBaseContext> options)
: base(options)
{
}
public opkDataBaseContext(DbContextOptions<opkData1Context> options)
{
this.options1 = options;
}
public opkDataBaseContext(DbContextOptions<opkData2Context> options)
{
this.options2 = options;
}
public virtual DbSet<OrgUnits> OrgUnits { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
...
}
OnModelCreatingPartial(modelBuilder);
}
partial void OnModelCreatingPartial(ModelBuilder modelBuilder);
public void CreateNewOrganization(CreateCompleteOrgViewModel model)
{
var nameParameter = new SqlParameter("#TopLevelOrgName", model.Name);
var codeParameter = new SqlParameter("#Code", model.Code);
var DbNameParameter = new SqlParameter("#DBName", model.DbCatalog);
var debugParameter = new SqlParameter("#debug", "0");
var firstNameParameter = new SqlParameter("#FirstName", model.FirstName);
var lastNameParameter = new SqlParameter("#LastName", model.LastName);
var userNameParameter = new SqlParameter("#Username", model.UserName);
this.Database.ExecuteSqlRaw("CreateRootOrg #TopLevelOrgName, #Code, #DBName, #debug, #FirstName, #LastName, #Username",
nameParameter, codeParameter, DbNameParameter, debugParameter, firstNameParameter, lastNameParameter, userNameParameter);
}
Here is my Startup.cs
public void ConfigureServices(IServiceCollection services)
{
if (_env.IsProduction())
{
var opkCoreConnection = Configuration.GetConnectionString("opkCoreDatabase");
services.AddDbContext<opkCoreContext>(options => options.UseSqlServer(opkCoreConnection));
var opkData1Connection = Configuration.GetConnectionString("opkData1Database");
services.AddDbContext<opkData1Context>(options => options.UseSqlServer(opkData1Connection));
var opkData2Connection = Configuration.GetConnectionString("opkData2Database");
services.AddDbContext<opkData2Context>(options => options.UseSqlServer(opkData2Connection));
var opkDataLocalBaseConnection = Configuration.GetConnectionString("opkDataBaseDatabase");
services.AddDbContext<opkDataBaseContext>(options => options.UseSqlServer(opkDataLocalBaseConnection));
Then I have one of these for each database:
public partial class opkData1Context : opkDataBaseContext
{
public opkData1Context()
{
}
public opkData1Context(DbContextOptions<opkData1Context> options)
: base(options)
{
}
My current error is:
"Error while validating the service descriptor 'ServiceType: Models.DataModels.opkDataBaseContext Lifetime: Scoped ImplementationType: Models.DataModels.opkDataBaseContext': Unable to activate type 'Models.DataModels.opkDataBaseContext'. The following constructors are ambiguous:\r\nVoid .ctor(Microsoft.EntityFrameworkCore.DbContextOptions'1[Models.DataModels.opkDataBaseContext])\r\nVoid .ctor(Microsoft.EntityFrameworkCore.DbContextOptions'1[Models.opkData1Context])"} System.Exception {System.InvalidOperationException}
I have been messing with this all day. First, am I even going down the right path or is this just a dumb idea? Second, any idea where I am going wrong? Thank you!
I have a scenario with one database server but multiple databases all which share the same schema
This is very common, even a best-practice, in Software-as-a-Service (SaaS) applications.
While this is not obvious, it turns out to be quite simple. You just need some way to pick the connection string at runtime, probably based on a combination of the config and something in the HttpContext (like the user's identity, the path, the host header, etc). Then you configure the DbContext for DI like this:
public void ConfigureServices(IServiceCollection services)
{
services.AddHttpContextAccessor();
services.AddDbContext<MyDbContext>((sp, opt) =>
{
var httpContext = sp.GetRequiredService<IHttpContextAccessor>();
var config = sp.GetRequiredService<IConfiguration>();
string connectionString = GetConnectionStringFromHttpContext(httpContext, config);
opt.UseSqlServer(connectionString, o => o.UseRelationalNulls());
});
services.AddControllers();
}
where GetConnectionStringFromHttpContext is a custom method that builds the connection string based on the config and the HttpContext.
You could take a look a feature introduced in EF Core 5, which can change the connection or connection string on an already initialized context
I want to use EF.Core 2.2.6 in a .Net Framework (4.6.2) project. I have created a separate project for the database.
I want to register the DbContext in the main project using dependency injection over the Prism framework (Unity).
var optionsBuilder = new DbContextOptionsBuilder<DbContext>();
optionsBuilder.UseSqlite(#"Data Source=CustomerDB.db");
containerRegistry.GetContainer().RegisterType<DbContext, CrossSettingContext>();
containerRegistry.GetContainer().RegisterType<DbContext>(new InjectionConstructor(optionsBuilder));
The database context:
public class CrossSettingContext : DbContext
{
private static Action<DbContextOptionsBuilder> onConfigure;
#pragma warning restore 649
public CrossSettingContext(DbContextOptions<CrossSettingContext> options) : base(options)
{
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.EnableSensitiveDataLogging(true);
onConfigure?.Invoke(optionsBuilder);
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Setting>().Map();
}
}
I get the following exception. The question is if I am using the right approach for registering EF Core.
System.InvalidOperationException: "No member matching data has been found.
Error in: RegisterType(Invoke.Constructor(Microsoft.EntityFrameworkCore.DbContextOptionsBuilder`1[Microsoft.EntityFrameworkCore.DbContext]))
I found this question -> but I need EF Core 2.2.6 and not Entity Framework 6.0
The answer from Haukinger is partially correct, but missing quite a bit of important information.
What you will want to do something like:
var optionsBuilder = new DbContextOptionsBuilder<CrossSettingContext>();
optionsBuilder.UseSqlite( #"Data Source=CustomerDB.db" );
However you do not need anything Container Specific AT ALL here. All you really need is:
containerRegistry.RegisterInstance(optionsBuilder.Options);
You do not actually need to register the CrossSettingContext if you want a new instance each time it's resolved. Though you could do the following if you want a singleton:
containerRegistry.RegisterSingleton<CrossSettingContext>();
When you want to use it you can just inject the context in your ViewModel/Services like:
public class ViewAViewModel
{
public ViewAViewModel(CrossSettingContext context)
{
// Do Stuff
}
}
I have a simple WPF/EF Core 2.2.4 application that uses postgres.
I'm analyzing the possible strategies to migrate it on SQL Server.
In non ORM applications, it's quite common to limit the database-specific reference to the connection string togheter with providing a way to dynamically load the database driver (thinking of JDBC model). In that model you have to address the problem of writing SQL that works cross databases.
Here the problem of SQL writing, actually the major one, is solved right from the start. So I find it quite paradoxical that we sort of reintroduce database dependency in the form of helper methods.
My first question is about the DbContext. The OnConfiguring receives a DbContextOptionsBuilder that is used to pass Connection string.
But in order to pass the connection string you use a database-specific method that is provided as an extension method by the database provider.
That is the optionsBuilder.UseNpgsql(connstr) in the following example.
How should I address this in a database-independend application?
class MyDbContext: DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
string connstr =
ConfigurationManager
.ConnectionStrings["MYAPP_PROD"].ConnectionString;
optionsBuilder.UseNpgsql(connstr);
}
}
The second question is: how can I load the entire database package in a dynamic way, so that I can manage to configure it instead of harcoding it?
Actually I use NuGet to get the package:
Npgsql.EntityFrameworkCore.PostgreSQL
Say that I want to use:
Microsoft.EntityFrameworkCore.SqlServer
How can this be done?
Use the strategy pattern to register the relevant database provider based on external configuration.
interface IDbProvider {
bool AppliesTo(string providerName);
DbContextOptions<T> LoadProvider<T>();
}
public class PostgresSqlProvider : IDbProvider {
public bool AppliesTo(string providerName) {
return providerName.Equals("Postgres");
}
public DbContextOptions<T> LoadProvider<T>() {
//load provider.
}
}
var providers = new [] {
new PostgresSqlProvider()
};
var selectedDbProvider = ""; //Load from user input / config
var selectedProvider = providers.SingleOrDefault(x => x.AppliesTo(selectedDbProvider));
if(selectedProvider == null) {
throw new NotSupportedException($"Database provider {selectedDbProvider} is not supported.");
}
var options = selectedProvider.LoadProvider<DbContext>();
This scenario is already covered by EF Core. Configuring providers should be done in Startup.ConfigureServices, using any of the AddDbContext methods that accept a builder action.
In the simplest case (dirtiest?), you can select providers based on a flag or a value that comes from the config system itself eg :
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
var connString=Configuration.GetConnectionString("SchoolContext");
var useSqlServer=Configuration.GetSection("MyDbConfig").GetValue<bool>("UseSqlServer");
services.AddDbContext<SchoolContext>(options =>{
if (useSqlServer)
{
options.UseSqlServer(connString);
}
else
{
options.UseNpgsql(connString);
}
});
}
or
var provider=Configuration.GetSection("MyDbConfig").GetValue<ProviderEnum>("Provider");
services.AddDbContext<SchoolContext>(options =>{
switch (provider)
{
case ProviderEnum.SqlServer:
options.UseSqlServer(connString);
break;
case ProviderEnum.Postgres :
options.UseNpgsql(connString);
break;
...
}
});
That flag can come from configuration as well, eg from the command-line, environment variables, etc.
Refactoring to .... lots
Extension method
This code can be extracted to an extension method on IServiceCollection, similar to other contexts, eg:
public static ConfigureContexts(this IServiceCollection services,string connString, string provider)
{
services.AddDbContext<SchoolContext>(options =>{
switch (provider)
{
case ProviderEnum.SqlServer:
options.UseSqlServer(connString);
break;
case ProviderEnum.Postgres :
options.UseNpgsql(connString);
break;
...
}
});
}
and used :
var connString=Configuration.GetConnectionString("SchoolContext");
var provider=Configuration.GetSection("MyDbConfig").GetValue<ProviderEnum>("Provider");
services.ConfigureContexts(provider,connString);
Builder picker
The builder, configuration patterns allow many variations that can handle complex scenarios. For example, we can pick a builder method in advance :
var efBuilder= SelectBuilder(provider,connString);
services.AddDbContext<SchoolContext>(efBuilder);
...
Action<DbContextOptionsBuilder> SelectBuilder(ProviderEnum provider,string connString)
{
switch (provider)
{
case ProviderEnum.SqlServer:
return ConfigureSql;
case ProviderEnum.Postgres :
return ConfigurePostgres;
}
void ConfigureSqlServer(DbContextOptionsBuilder options)
{
options.UseSqlServer(connString);
}
void ConfigurePostgres(DbContextOptionsBuilder options)
{
options.UseNpgSql(connString);
}
}
In C# 8 this could be reduced to:
Action<DbContextOptionsBuilder> SelectBuilder(ProviderEnum provider,string connString)
{
return provider switch (provider) {
ProviderEnum.SqlServer => ConfigureSql,
ProviderEnum.Postgres => ConfigurePostgres
};
void ConfigureSqlServer(DbContextOptionsBuilder options)
{
options.UseSqlServer(connString);
}
void ConfigurePostgres(DbContextOptionsBuilder options)
{
options.UseNpgSql(connString);
}
}
Concrete config class
Another possibility is to create a strongly-typed configuration class and have it provide the builder :
class MyDbConfig
{
public ProviderEnum Provider {get;set;}
....
public Action<DbContextOptionsBuilder> SelectBuilder(string connString)
{
return provider switch (provider) {
ProviderEnum.SqlServer => ConfigureSql,
ProviderEnum.Postgres => ConfigurePostgres
};
void ConfigureSqlServer(DbContextOptionsBuilder options)
{
options.UseSqlServer(connString);
}
void ConfigurePostgres(DbContextOptionsBuilder options)
{
options.UseNpgSql(connString);
}
}
}
and use it :
var dbConfig=Configuration.Get<MyDbConfig>("MyDbConfig");
var efBuilder=dbCongig.SelectBuilder(connString);
services.AddDbContext<SchoolContext>(efBuilder);
I have a project with multiple DbContext classes: one for every domain. Since EF Core isn't perfect I have some functionality I have to add to every DbContext like allowing it to handle the new JSON functionality of SQL Server 2017. There is other functionality I'm adding too but for the sake of brevity I have removed it from the example.
To add this JSON functionality to every DbContext I work with a BaseDbContext which is an abstract class that simply extends the DbContext. One of the prerequisites for the functionality is interception of SQL queries that are sent to the database. To perform this I make use of the tactic described here.
In the next few weeks we are moving into different development environments and I want to inject the correct connection string based on the current environment through the Options pattern. This doesn't play well with the interception tactic. Since to perform interception GetService<DiagnosticSource>() is called which actually triggers the OnConfiguring function BEFORE the continuation of the constructor of my SomeDbContext, which means my options are never filled in leading to a NullReferenceException.
How can I extend DbContext without triggering OnConfiguring while at the same time avoiding code duplication? I can also run a custom EF Core but I'd like to avoid that if at all possible.
public abstract class BaseDbContext : DbContext, IBaseDbContext
{
protected BaseDbContext()
{
DiagnosticListener listener = this.GetService<DiagnosticSource>() as DiagnosticListener; // This calls OnConfiguring.
listener.SubscribeWithAdapter(new JsonInterceptor());
}
[DbFunction("JSON_VALUE", "")]
public static string JsonValue(string source, string path)
{
throw new NotSupportedException();
}
[DbFunction("TRY_CAST", "")]
public static string TryCast(string source, string typeName)
{
throw new NotSupportedException();
}
}
public class SomeDbContext : BaseDbContext, ISomeDbContext
{
private readonly SomeDbContextOptions _options;
public DbSet<Order> Orders { get; set; }
public SomeDbContext(IOptions<SomeDbContextOptions> options)
{
_options = options.Value;
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
// This is called before _options is set meaning it is null in the line below.
optionsBuilder
.UseSqlServer(_options.ConnectionString);
}
}
I'm trying to create a base dbcontext that contains all the common entities that will always be reused in multiple projects, like pages, users, roles, navigation etc.
In doing so I have a ContextBase class that inherits DbContext and defines all the DbSets that I want. Then I have a Context class that inherits ContextBase where I define project specific DbSets. The classes are defined as follows:
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 my global.asax:
Database.SetInitializer(new MigrateDatabaseToLatestVersion<Context, Configuration>());
where Configuration referes to a class inheriting DbMigrationsConfiguration and overriding the Seed method.
The two context classes are defined in the same namespace, but cross assembly (in order that I may update the base project in multiple existing projects without touching the project specific code) - not sure if this is relevant.
MY PROBLEM:
When running this code, it works fine, but when looking in the Database, it actually creates two different databases!! One containing all the base entity tables and one containing BOTH base and custom tables. CRUD operations are only performed on the custom version (which is obviousely what I want), but why does it create the schema of the other one as well?
Any help is appreciated, thanks!
UPDATE:
The following code is what I ended up with. It isn't ideal, but it works. I would still love to get feedback on ways to improve this, but in the meantime I hope this helps further the process. I REALLY DO NOT RECOMMEND DOING THIS! It is extremely error prone and very frustrating to debug. I'm merely posting this to see if there is any better ideas or implementations to achieve this.
One (but not the only) issue still existing is that the MVC views have to be manually added to projects. I've added it to the Nuget package, but it takes 2 to 3 hours to apply a nuget package with so many files when VS is connected to TFS. With some more work and a custom View engine the views can be precompiled (http://blog.davidebbo.com/2011/06/precompile-your-mvc-views-using.html).
The solution is split into the Base Framework projects and the Custom projects (each category includes its own models and repository pattern). The framework projects are packaged up in a Nuget package and then installed in any custom projects allowing the common functionality of any project like user, role and permission management, content management, etc (often referred to as the Boiler Plate) to be easily added to any new projects. This allows any improvements of the boilerplate to be migrated in any existing custom projects.
Custom Database 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's DB Migrations Configuration:
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);
}
}
Custom Project's DB Migrations Configuration:
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);
}
}
The custom 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());
}
}
Framework 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);
}
In the global.asax AppStart:
//first remove the base context initialiser
Database.SetInitializer<ContextBase>(null);
//set the inherited context initializer
Database.SetInitializer(new MyMigrateDatabaseToLatestVersion());
In the 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>
(from the comments)
You're creating ContextBase objects directly, apparently as new T() in a generic method with ContextBase as a generic type argument, so any initialisers for ContextBase also run. To prevent creating ContextBase objects (if it should never be instantiated directly, if the derived context should always be used), you can mark the class as abstract.
Your ContextBase seems to have an initializer as well.. You can remove this by
Database.SetInitializer<ContextBase>(null);