#c# #entity-framework
#c# #entity-framework
Вопрос:
У меня есть строка подключения, и я могу сделать это без проблем
<connectionStrings>
<add name="DbName"
connectionString="server=serverName;database=DbTest;user=x;pwd=xxx;"
providerName="System.Data.SqlClient" />
</connectionStrings>
и у меня есть соединение Entity Framework:
public DbContext1() : base("DbName")
{
}
Но мне нужно сделать запрос DbContext1
, чтобы получить новое строковое соединение из таблицы для подключения к другой базе данных, но я не знаю, как использовать строковое соединение, которое я получаю из запроса.
Как я могу использовать строковое соединение из таблицы для создания нового DbContext
?
Ответ №1:
Сделайте что-то вроде этого:
public DbContext1(string connString) : base(connString)
{
}
Конструктор, который требуется вызвать вашему производному классу, — это этот. Аргумент string обрабатывается либо как сама допустимая строка подключения, либо как имя строки подключения.
Ответ №2:
Это похоже на многопользовательский сценарий, в котором пользователи проходят аутентификацию в центральной базе данных, а затем направляются к определенному экземпляру базы данных, содержащему их собственные данные. В качестве простого примера во время аутентификации:
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();
}
В идеале, если вы сохраняете данные пользователя (идентификатор пользователя, имя и т.д.) в состоянии сеанса, вы можете загрузить соответствующую строку подключения и сохранить ее как часть этой структуры данных.
Затем создайте класс 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.
Для ASP.Net apps, использующие сеанс, вам может потребоваться завершить Session
, чтобы библиотека внедрения зависимостей могла разрешить строку подключения / структуру пользователя из текущего состояния сеанса.
Опять же, это лишь очень элементарный пример, описывающий вариант упрощения динамических строк подключения, предполагающий что-то вроде ASP.Сетевое веб-приложение. Следует рассмотреть дополнительные меры безопасности, но, надеюсь, это должно дать некоторые идеи о том, как это можно структурировать.