在这里,我有一个特定的场景,我需要根据用户传递连接字符串,因为可能会根据用户的企业将用户映射到不同的数据库。
这是我使用静态变量解析依赖关系的代码:
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组件的项目中,它只是一个安装程序项目,该项目基本上是专门为解决依赖关系而设计的。
我的通用存储库如下所示
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 Controller的构造函数中已在数据库中设置了设置,因此我们无需在任何地方进行设置
public abstract class BaseController : Controller
{
public BaseController(IUserRepository userRepository)
{
userRepository.connectionStringProvider.Provider = WebUtilities.CurrentUserData.Provider;
userRepository.connectionStringProvider.ConnectionString = WebUtilities.CurrentUserData.ConnectionString;
}
}
由于连接字符串是运行时数据,因此不应使用它来构造您的应用程序组件,如本文所述。因此,如本文所建议,您应该将连接字符串隐藏在提供程序抽象的后面。例如:
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
to将为您获取正确的连接字符串将很简单:
class DatabaseConnectionStringProvider : IConnectionStringProvider
{
public string ConnectionString => Session["connectionString"];
}
由于此分类取决于特定于应用程序的内容(在这种情况下为ASP.NET会话),因此该类不应成为应用程序核心逻辑的一部分。相反,此适配器应位于应用程序的启动路径(即合成根,即配置容器的位置)中。
您甚至可能要考虑不要将传递IConnectionStringProvider
到存储库中,而是创建一个将创建连接本身的抽象。这将掩盖一个事实,即完全有一个连接字符串。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句