The context is being used in Code First mode with code that was generated from an EDMX file
Asked Answered
A

1

2

I am developing an MVC 5 application with EF 6 database first approach. Now I want my DbContext to access multiple databases based on different Users. For that matter I generated a connection string in Web.Config file as:

string str = u.Users.Where(x => x.UserName == HttpContext.User.Identity.Name).First().ConnStr;
var configuration = WebConfigurationManager.OpenWebConfiguration("~");
var section = (ConnectionStringsSection)configuration.GetSection("connectionStrings");          
ConnectionStringSettings c = new ConnectionStringSettings();    
c.ConnectionString = str;
c.Name = u.Users.Where(x => x.ConnStr == str).First().DbName;
c.ProviderName = "System.Data.SqlClient";
section.ConnectionStrings.Add(c);
configuration.Save();

The connection string generated in config file is:

<add name="Awais123" connectionString="Data Source=.;Initial Catalog=Awais123;integrated security=True;MultipleActiveResultSets=True"
      providerName="System.Data.SqlClient" />

And the Connection String generated by EF when I made EDMX is:

<add name="ABCEntities" connectionString="metadata=res://*/Models.awais.csdl|res://*/Models.awais.ssdl|res://*/Models.awais.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=.;initial catalog=Awais;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework&quot;"
      providerName="System.Data.EntityClient" />

Then I overloaded my Entities constructor as:

public ABCEntities(string nameorConnString) : base(nameorConnString) {}

And the default Constructor is:

public ABCEntities() : base("name=ABCEntities") {}

Now I declare another DbContext class in another .cs file to generate the database as:

public partial class NewDbGen : DbContext
{
     public NewDbGen(string nameorConnString): base(nameorConnString)
     { Database.Create(); }
}

I am calling the DbContext objects as:

private static string str = u.Users.Where(x => x.UserName == HttpContext.User.Identity.Name).First().ConnStr;
private NewDbGen de = new NewDbGen(str); // for creating a new database
private ABCEntities db = new AbcEntities(str); // my original Entites.. and all my controllers use these entites for all queries

Now all this runs successfully and database is created in SQL Server. But later when I tried to query on that database an error occured in:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
     throw new UnintentionalCodeFirstException();
}

And it throws an error

The context is being used in Code First mode with code that was generated from an EDMX file for either Database First or Model First development. This will not work correctly. To fix this problem do not remove the line of code that throws this exception. If you wish to use Database First or Model First, then make sure that the Entity Framework connection string is included in the app.config or web.config of the start-up project. If you are creating your own DbConnection, then make sure that it is an EntityConnection and not some other type of DbConnection, and that you pass it to one of the base DbContext constructors that take a DbConnection. To learn more about Code First, Database First, and Model First see the Entity Framework documentation here: http://go.microsoft.com/fwlink/?LinkId=394715

What can I do? I have to use single DbContext for all User Databases and same object of ABCEntities i.e. "db" to access database in controller methods. I have already looked into this question DbFactory method, but the same error occured.

I want to make a Single Instance Multi-Tenant application

Regards.

Abrahamsen answered 1/10, 2015 at 11:21 Comment(0)
P
8

When you are using Database-First approach and you use edmx, then using OnModelCreating makes no sense.

To have a single instance application that uses database per tenant strategy, you should:

  • Use a single dbcontext class for all tenants
  • Add an overload to your dbcontext constructor that accept connnectionstring
  • create a database for each tenant
  • create connectionstring at run-time based on your tenant detection strategy
  • create an instance of dbcontext passing the connectionstring that you created at run-time based on your tenant detection strategy
Pulitzer answered 1/10, 2015 at 12:5 Comment(1)
Lae but still it could be helpful to someone.Shiner

© 2022 - 2024 — McMap. All rights reserved.