У меня есть конкретный сценарий здесь, где мне нужно передать строку соединения на основе пользователя, поскольку пользователи могут быть сопоставлены с различными базами данных на основе его/ее предприятия.Как разрешить зависания во время выполнения в виндсерке замка для C#
Это код, который я использую для разрешения зависимости со статической переменной:
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(
Component.For<IUserRepository>()
.ImplementedBy(typeof(IKS.Dare.Optimix.Repository.EntityFramework.UserModule.UserRepository))
.DependsOn(Dependency.OnValue("connectionString", DatabaseSettings.DefaultConnectionString))
);
}
Поскольку этот DefaultConnectionString
должен быть динамичным, я не хочу, чтобы заблокировать эту переменную, чтобы сделать нить так как это ухудшит производительность. Я бы хотел, чтобы я мог справиться с такой ситуацией.
Возможное соображение, которое может быть то, что мы можем дать сеанс, который может быть применен следующим образом:
DynamicParameters((k, d) => d["connectionString"] = Session["connectionString"])
Но это в другом проекте, который не использует какой-либо веб-компонент, это просто инсталлятор проект, который в основном предназначен только для разрешения зависимостей.
Мой Generic хранилище выглядит следующим образом
public class GenericRepository<T> : IGenericRepository<T> where T : BaseEntity
{
private const string IsActive = "IsActive", DbContext = "dbContext", EntityPropertyName = "Entity";
private string connectionString = String.Empty, provider = String.Empty;
public GenericRepository(string connectionString, string provider)
{
this.connectionString = connectionString;
this.provider = provider;
}
public int Count()
{
string tableName = typeof(T).Name;
string query = SqlQueryConstants.SelectCount + SqlQueryConstants.Space + tableName;
int count = DbHelper.ExecuteScalar<int>(query: query, commandType: System.Data.CommandType.Text, connectionString: connectionString, provider: provider, parameters: null);
return count;
}
}
класс DBHelper выглядит следующим образом
public static int ExecuteNonQuery(string query, CommandType commandType = CommandType.StoredProcedure,
IList<DbParameter> parameters = null, int? timeout = null, string connectionString = "", string provider = "")
{
using (var connection = CreateDbConnection(connectionString, provider))
{
connection.Open();
using (DbCommand command = CreateDbCommand(sqlQuery: query, parameters: parameters,
connection: connection, commandType: commandType, timeout: timeout))
{
return command.ExecuteNonQuery();
}
}
}
public static DbParameter CreateParameter<TValue>(string name, TValue value, DbType dbType,
ParameterDirection parameterDirection = ParameterDirection.Input, string provider = "")
{
DbParameter param = CreateDbProviderFactory(provider).CreateParameter();
param.Value = value;
param.ParameterName = name;
param.DbType = dbType;
param.Direction = parameterDirection;
return param;
}
public static DbConnection CreateDbConnection()
{
return CreateDbConnection(String.Empty, String.Empty);
}
public static DbConnection CreateDbConnection(string connectionString = "", string provider = "")
{
DbConnection connection = null;
if (String.IsNullOrEmpty(provider))
{
if (String.IsNullOrEmpty(DatabaseSettings.DefaultProvider))
throw new ArgumentNullException("provider");
else
provider = DatabaseSettings.DefaultProvider;
}
connection = CreateDbProviderFactory(provider).CreateConnection();
connection.ConnectionString = connectionString;
return connection;
}
Любая помощь будет принята с благодарностью.
Примечание: я не мог отредактировать ответ Стивена. [EDIT] Для того, чтобы сделать его более ясным, он может быть реализован как:
Здесь контроллер наследуется от BaseController
public class UserController : BaseController
{
//
// GET: /Index/
private IUserRepository userRepository;
public UserController(IUserRepository userRepository)
: base(userRepository)
{
this.userRepository = userRepository;
}
}
и BaseController наследуется от контроллера, где в настройках базы данных создаются в конструкторе Базовый контроллер, поэтому нам не нужно его устанавливать везде
public abstract class BaseController : Controller
{
public BaseController(IUserRepository userRepository)
{
userRepository.connectionStringProvider.Provider = WebUtilities.CurrentUserData.Provider;
userRepository.connectionStringProvider.ConnectionString = WebUtilities.CurrentUserData.ConnectionString;
}
}
Данные времени выполнения [не должны вставляться в конструктор ваших компонентов] (https://www.cuttingedge.it/blogs/steven/pivot/entry.php?id=99). – Steven
@Steven, я понимаю вашу точку зрения, но у меня есть ситуация, когда мои репозитории зависят от переменной строки подключения и поставщиков. Можете ли вы предложить мне лучший подход? –
Прежде всего, поскольку у вас будет возможно много репозиториев, для которых требуется соединение, скройте строку подключения за абстракцией 'IConnectionFactory' или' IDbContextProvider' (в зависимости от ваших потребностей). При такой абстракции становится тривиальным создание реализации адаптера, которая получает правильную строку соединения во время выполнения и создает либо новый SqlConnection, либо DbContext. Репозиторий, чем вызовы 'connectionFactory.CreateConnection()' или 'dbContextProvider.CurrentContext'. – Steven