Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
926 views
in Technique[技术] by (71.8m points)

c# - The context is being used in Code First mode with code that was generated from an EDMX file

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.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...