首页 > 解决方案 > 使连接实体框架动态

问题描述

我有一个连接字符串,我可以毫无问题地做到这一点

<connectionStrings>
    <add name="DbName" 
         connectionString="server=serverName;database=DbTest;user=x;pwd=xxx;"
         providerName="System.Data.SqlClient"  />
</connectionStrings>

我有实体框架的连接:

public DbContext1() : base("DbName")
{
}

但是我需要进行查询以DbContext1从表中获取新的字符串连接以连接到其他数据库,但我不知道如何使用从查询中收到的字符串连接。

如何使用表中的字符串连接来创建新的DbContext

标签: c#entity-framework

解决方案


这听起来像是一个多租户场景,其中用户对中央数据库进行身份验证,然后被定向到包含他们自己的数据的特定数据库实例。作为身份验证期间的一个简单示例:

using (var context = new AuthDbContext())
{ // Where AuthDbContext is the central DB containing authentication and the connection string to that user's home database..
     // ... On successful authentication...
     var connectionString = context.Tenants
         .Where(x => x.TenantId == authenticatedUser.TenantId)
         .Select(x => x.ConnectionString)
         .Single();
}

理想情况下,如果您将用户详细信息(用户 ID、名称等)保存到会话状态,那么您可以加载关联的连接字符串并将其保存为该数据结构的一部分。

然后创建一个 AppDbContextFactory 类或 UnitOfWork 模式类以注入您的服务/控制器,以根据当前用户的连接字符串提供 DbContext。

作为一个非常基本的例子:

public interface IUserStateFacade
{
    string CurrentUserConnectionString { get; }
}

public class UserSessionState : IUserStateFacade
{
   public const string UserStateSessionName = "UserState";
   public string CurrentUserConnectionString
   {
       get 
       {
           var userState = (UserSessionState)Session[UserStateSessionName] ?? throw new ApplicationException("Session state missing/expired.");
           return userState.ConnectionString;
       }
   }
}

public interface IAppContextFactory
{
    AppContext Create();
}

public class AppContextFactory
{
    private readonly IUserStateFacade _userState = null;
   
    public AppContextFactory(IUserStateFacade userState)
    {
        _userState = userState ?? throw new ArgumentNullException("userState");
    }
    
    /// <summary>
    /// Create a DbContext. Calling code is responsible for disposing.
    /// </summary>
    public AppContext Create()
    {
        return new AppContext(_userState.ConnectionString);
    }
}

然后在您的控制器等中,通常希望使用默认构造函数创建或注入 DbContext 将改为使用以下内容:

using (var context = AppContextFactory.Create())
{ }

或者注入一个通过 AppContextFactory 初始化的值。

对于使用 Session 的 ASP.Net 应用程序,您可能需要进行包装Session,以便依赖注入库可以将连接字符串/用户结构解析出当前会话状态。

同样,这只是一个非常基本的示例,用于概述一个选项以促进动态连接字符串,假设类似于 ASP.Net Web 应用程序。应该考虑额外的安全措施,但它应该有望提供一些关于如何构建它的想法。


推荐阅读