我在这里有一个特定的场景,我需要根据用户传递连接字符串,因为用户可能会根据他/她的企业映射到不同的数据库。
这是我用来解决静态变量依赖的代码:
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"])
但是这是一个不使用任何Web组件的不同项目,它只是一个安装程序项目,基本上只用于解析依赖项。
My 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;
}
非常感谢任何帮助。
注意:我无法编辑史蒂文的答案。 [编辑]为了使其更清楚,它可以实现为:
此处控制器继承自BaseController
public class UserController : BaseController
{
//
// GET: /Index/
private IUserRepository userRepository;
public UserController(IUserRepository userRepository)
: base(userRepository)
{
this.userRepository = userRepository;
}
}
和BaseController继承自Controller,其中数据库设置在Base控制器的构造函数中设置,因此我们不需要在任何地方设置它
public abstract class BaseController : Controller
{
public BaseController(IUserRepository userRepository)
{
userRepository.connectionStringProvider.Provider = WebUtilities.CurrentUserData.Provider;
userRepository.connectionStringProvider.ConnectionString = WebUtilities.CurrentUserData.ConnectionString;
}
}
答案 0 :(得分:3)
由于连接字符串是运行时数据,因此不应使用它来构建应用程序组件,如this article中所述。因此,在文章建议中,您应该隐藏提供者抽象背后的连接字符串。例如:
public interface IConnectionStringProvider {
string ConnectionString { get; }
}
这样,您的存储库可以依赖于IConnectionStringProvider
,并且可以在运行时调用IConnectionStringProvider.ConnectionString
:
public int Count()
{
string tableName = typeof(T).Name;
string query = SqlQueryConstants.SelectCount + SqlQueryConstants.Space + tableName;
return DbHelper.ExecuteScalar<int>(
this.connectionStringProvider.ConnectionString,
provider: provider, parameters: null);
}
创建IConnectionStringProvider
以获取正确的连接字符串将是微不足道的:
class DatabaseConnectionStringProvider : IConnectionStringProvider
{
public string ConnectionString => Session["connectionString"];
}
由于此clas依赖于特定于应用程序(在本例中为ASP.NET会话),因此该类不应该是应用程序核心逻辑的一部分。相反,这个适配器应该存在于应用程序的启动路径中(例如,组合根,配置容器的位置)。
您甚至可能想要考虑不将IConnectionStringProvider
传递到您的存储库中,而是创建一个将自己创建连接的抽象。这将隐藏完全存在连接字符串的事实。
答案 1 :(得分:0)
您正在寻找的是多租户。您可以谷歌“castle windsor multi tenancy”并找到一些有用的文章。
这是一个类似的Stackoverflow question链接到一些关于温莎和多租户的好文章。特别要看看温莎的IHandlerSelector界面。