c# - 使用具有单个 DbContext 和 Entites 的多个数据库并在运行时生成 Conn String

标签 c# sql-server asp.net-mvc entity-framework

我正在开发 MVC 5 应用程序。最初我使用单一数据库和 EF6 数据库优先方法,我使用我的 DbContext 实例访问我的数据库,它有 102 个表。我将其实例声明为:

private MyEntities db = new MyEntities();

现在我想允许多家公司使用我的应用程序,为此我必须为每家新公司创建一个新数据库。我通过如下向我的 DbContext 声明另一个构造函数来实现此目的:

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

然后将其实例声明为:

public NewEntities de = new NewEntities((ConfigurationManager.ConnectionStrings["NewEntities123"]).ToString());

然后我打电话

db.Database.Create();

我的新数据库已成功创建。但是在这个方案中,每次我想添加一个数据库时,我都必须在我的 Web.config 文件中声明一个新的连接字符串。

是否有任何方法可以根据配置文件中的公司名称自动生成连接字符串,然后将其传递给构造函数以使用该名称创建一个新数据库?

此外,我想为每个公司使用相同的“db”实例和 DbContext 访问我的所有 Controller 方法,以便我的相同代码可以用于所有公司。如何访问多个数据库的单个 DbContext 及其实例?

我已经看过answer to this正如它所说,没有方法。但是我的应用程序如何为多个用户工作?

最佳答案

当数据库优先时,有一个带有映射的 edmx 文件,您可以通过这种方式创建和使用数据库。

向您的上下文构造函数添加一个重载(就像您所做的那样),例如:

public TenantDBContainer(string connectionString)
    : base(connectionString)
{
}

然后当您需要创建数据库(如果不存在)时,使用 yourContextInstance.Database.CreateIfNotExists();

var connectionStringTemplate =
    @"metadata=res://*/Models.TenantDB.csdl|res://*/Models.TenantDB.ssdl|res://*/Models.TenantDB.msl;" +
    @"provider=System.Data.SqlClient;" +
    @"provider connection string=""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 connectionString = string.Format(connectionStringTemplate, TenandDBName, TenantUserName, TenantPassword);
var db = new TenantDBEntities(connectionString);
db.Database.CreateIfNotExists();

注意:

  • 通过这种方式,在 Multi-Tenancy 应用程序中,您可以为每个租户创建数据库并使用它。
  • 您无需更改 webconfig 即可在其中添加连接字符串,只需在运行时创建连接字符串即可。
  • 现在您可以根据租户检测策略设计一个结构获取上下文

作为简化案例的示例,假设您在某处有一个静态方法为您返回一个上下文实例,例如:

Public class DbHelper
{
    public static TenantDBEntities GetDbContext(string tenantName)
    {
        var connectionStringTemplate =
            @"metadata=res://*/Models.TenantDB.csdl|res://*/Models.TenantDB.ssdl|res://*/Models.TenantDB.msl;" +
            @"provider=System.Data.SqlClient;" +
            @"provider connection string=""data source=(localdb)\v11.0;" +
            @"initial catalog={0};"+
            @"integrated security=True;" +
            @"MultipleActiveResultSets=True;App=EntityFramework"";";

        var TenandDBName = "TenantDB_" + tenantName;
        var connectionString = string.Format(connectionStringTemplate, TenandDBName);
        var db = new TenantDBEntities(connectionString);
        db.Database.CreateIfNotExists();

        return db;
    }
}

假设我的租户检测策略只是基于请求 url 或其他东西。

现在,例如在 Index 操作中的 ProductController 中,您可以这样使用它;

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

当每个租户使用此操作时,它会连接到适合该租户的数据库,如果数据库不存在,则首先创建它然后使用它。

这样每个租户都会看到自己的产品。

关于c# - 使用具有单个 DbContext 和 Entites 的多个数据库并在运行时生成 Conn String,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32865627/

相关文章:

jquery - 如何在 ASP.NET MVC 操作中注册 javascript?

c# - 不明确的调用 asp.net mvc 操作方法

c# - 类型 null 不可分配给类型 IJobDetails(这是我的接口(interface))

C# 变量不会更新

sql - SQL Server 2008 中的内连接删除?

sql-server - SQL SERVER sp_executesql ')' 附近的语法不正确

c# - 为什么razor会自动四舍五入到小数点后2位?

c# - 类型编译错误后新表达式需要 () 或 [] - C#

c# - 我的表单上有一个按钮,单击后会运行更新 sql 来更新数据库上的忠诚度积分,但它不会更新

Python使用sqlcmd执行sql查询