Luca Morelli
Luca Morelli

Reputation: 2560

Configure more than one dbcontext in EF 7

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

Upvotes: 0

Views: 6080

Answers (4)

Austin_Anderson
Austin_Anderson

Reputation: 940

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.

Upvotes: 0

crgolden
crgolden

Reputation: 4634

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

Upvotes: 0

bricelam
bricelam

Reputation: 30425

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

Upvotes: 2

cwiederspan
cwiederspan

Reputation: 95

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

Upvotes: 1

Related Questions