Utilisation de plusieurs bases de données avec un seul DbContext et Entités et génération de Conn Ssortingng à l'exécution

Je développe une application MVC 5. Initialement, j'utilisais une database unique avec la première approche EF6 DataBase et j'utilise mon instance DbContext pour accéder à ma database qui contient 102 tables. Je déclare son instance comme:

MyEntities privé db = new MyEntities ();

Maintenant, je veux permettre à plusieurs entresockets d'utiliser mon application et d'ailleurs je dois créer une nouvelle database pour chaque nouvelle entreprise. J'ai réalisé ceci en déclarant un autre constructor à mon DbContext comme suit:

public partial class NewEntities : DbContext { public NewEntities(ssortingng name) : base(name) { } } 

Et puis déclarer son instance comme:

 public NewEntities de = new NewEntities((ConfigurationManager.ConnectionSsortingngs["NewEntities123"]).ToSsortingng()); 

Puis j'ai appelé

db.Database.Create ();

et ma nouvelle database a été créée avec succès. Mais dans ce schéma, je dois déclarer une nouvelle string de connection dans mon file Web.config chaque fois que je veux append une database.

Existe-t-il une méthode dans laquelle une string de connection est générée automatiquement selon le nom de la société dans le file de configuration, puis transmise au constructor pour créer une nouvelle database avec ce nom?

De plus, je veux accéder à toutes les methods de mon controller avec la même instance "db" et DbContext pour chaque entreprise, afin que mon même code puisse être utilisé pour toutes les entresockets. Comment puis-je accéder à un seul DbContext et à son instance pour plusieurs bases de données?

J'ai déjà cherché réponse à cela car il dit qu'il n'y a pas de méthode. Mais alors, comment mon application peut-elle fonctionner pour plusieurs users?

Lorsque vous utilisez la database en premier, avec un file edmx avec des mappages, vous pouvez créer et utiliser la database de cette façon.

append une surcharge à votre constructor de context (comme vous l'avez fait), par exemple:

 public TenantDBContainer(ssortingng connectionSsortingng) : base(connectionSsortingng) { } 

Ensuite, lorsque vous avez besoin de créer une database si elle n'existe pas, utilisez yourContextInstance.Database.CreateIfNotExists();

 var connectionSsortingngTemplate = @"metadata=res://*/Models.TenantDB.csdl|res://*/Models.TenantDB.ssdl|res://*/Models.TenantDB.msl;" + @"provider=System.Data.SqlClient;" + @"provider connection ssortingng=""data source=(localdb)\v11.0;" + @"initial catalog={0};"+ @"user id={1};password={2};" + @"MultipleActiveResultSets=True;App=EntityFramework"";"; var TenandDBName = "Database Name Based on Tenant"; var TenantUserName = "UserName Based on Tenant"; var TenantPassword = "Password Based on Tenant"; var connectionSsortingng = ssortingng.Format(connectionSsortingngTemplate, TenandDBName, TenantUserName, TenantPassword); var db = new TenantDBEntities(connectionSsortingng); db.Database.CreateIfNotExists(); 

Remarque:

  • De cette façon, dans une application multi-locataire, vous pouvez créer une database par locataire et l'utiliser.
  • Vous n'avez pas besoin de changer votre webconfig pour y append une string de connection, vous pouvez simplement créer une string de connection au moment de l'exécution.
  • Vous pouvez maintenant concevoir une structure pour get le context en fonction de votre stratégie de détection des locataires .

A titre d'exemple pour simplifier le cas, supposons que vous ayez une méthode statique quelque part qui renvoie une instance de context pour vous, par exemple:

 Public class DbHelper { public static TenantDBEntities GetDbContext(ssortingng tenantName) { var connectionSsortingngTemplate = @"metadata=res://*/Models.TenantDB.csdl|res://*/Models.TenantDB.ssdl|res://*/Models.TenantDB.msl;" + @"provider=System.Data.SqlClient;" + @"provider connection ssortingng=""data source=(localdb)\v11.0;" + @"initial catalog={0};"+ @"integrated security=True;" + @"MultipleActiveResultSets=True;App=EntityFramework"";"; var TenandDBName = "TenantDB_" + tenantName; var connectionSsortingng = ssortingng.Format(connectionSsortingngTemplate, TenandDBName); var db = new TenantDBEntities(connectionSsortingng); db.Database.CreateIfNotExists(); return db; } } 

Et supposons que ma stratégie de mise à jour de locataire est simplement basée sur l'URL de request ou autre chose.

Maintenant, par exemple dans ProductController dans l'action Index, vous pouvez l'utiliser de cette façon;

 public ActionResult Index() { var tenantName = "Get tenant based on your strategy, for example tenant1 or tenant2"; var db= DbHelper.GetDbContext(tenantName) var model= db.Products.ToList(); return View(model); } 

Lorsque chaque locataire travaille avec cette action, il se connecte à la database appropriée pour ce locataire, et si la database n'existe pas, crée d'abord puis l'utilise.

De cette façon chaque locataire verra ses propres produits.

Vous pourriez utiliser une usine pour faire quelque chose de similaire à ce que vous essayez de faire. Il n'y aurait pas d'autre moyen d'utiliser un seul DbContext pour plusieurs bases de données sans spécifier la database à laquelle vous essayez de vous connecter. Le problème avec ce que vous essayez de faire est que les entités dans le context devraient exister dans les deux bases de données. Je pense que ce que vous voulez vraiment, c'est une usine qui produit plusieurs classs DbContext (deuxième exemple).

  void Main() { var factory = new DBFactory(); var context = factory.GetContext("NewEntities123"); var context2 = factory.GetContext("SomeOtherDatabase"); } public class DBFactory { public DBContext GetContext(ssortingng dbName) { return new NewEntities((ConfigurationManager.ConnectionSsortingngs[dbName]).ToSsortingng()); } } void Main() { //instead of passing in the database name here you could //just use a single config value for a database and that //database would be different for your different apps //then it would just be var context = factory.GetContext(); var context = factory.GetContext("NewEntities123"); } public class DBFactory { public DBContext GetContext(ssortingng dbName) { switch(dbName) { case "NewEntities123": return new NewEntities((ConfigurationManager.ConnectionSsortingngs[dbName]).ToSsortingng()); case "SomeOtherDatabase": return new SomeOtherEntities((ConfigurationManager.ConnectionSsortingngs[dbName]).ToSsortingng()); } } } 

Le paramètre passé dans votre constructor DbContext peut être un nom ou une string de connection. Si vous générez juste votre string de connection quelque part et que vous la transmettez quand la class est créée, tout devrait fonctionner correctement.