我正在尝试创建一些“存储库”样式类,以通过DapperWrapper包装对Dapper的调用。尝试将SqlExecutor注入存储库,检查属性以确定要连接的数据库。
这是存储库实现,因此您可以看到我想要做的事情:
public class ProviderRepository : IProviderRepository<SearchType>
{
private readonly IDbExecutor executor;
public ProviderRepository([BHN]IDbExecutor executor)
{
this.executor = executor;
}
public IList<SearchType> GetAllSearchTypes()
{
return executor
.Query<SearchType>("BHN.pSEL_LU_SEARCHTYPE_Load", commandType: CommandType.StoredProcedure)
.ToList();
}
}
这是我的ninject绑定,我知道这很糟糕但只是为了说明我想要做的事情:
kernel.Bind<IDbExecutor>().To<SqlExecutor>()
.WhenTargetHas<BHNAttribute>()
.WithConstructorArgument("sqlConnection",
new SqlConnection(connections["ProviderSearch"].ConnectionString));
注意:BHNAttribute只是一个继承自Attribute的空类。
现在明显的问题是在应用程序启动时创建了sql连接,我明白了,但是如何在使用它而不是在应用程序加载时进行加载?我一直在玩Ninject Factory扩展,但是我遇到了实现可能会出现问题的问题。所以我创造了这个:
public class ExecutorFactory
{
private ISqlExecutorFactory executor;
public ExecutorFactory(ISqlExecutorFactory executor)
{
this.executor = executor;
}
public void Do()
{
var e = this.executor.CreateSqlExecutor("string");
}
}
public interface ISqlExecutorFactory
{
SqlExecutor CreateSqlExecutor(string conn);
}
我的绑定看起来像这样:
kernel.Bind<ISqlExecutorFactory>.ToFactory();
工厂类中的“字符串”将是“ProviderSearch”并且需要传递给我假设的ToFactory()方法,但我不明白我将如何做到这一点并结合使用BHNAttribute,就像我一样以前做过。或者,如果在这一点上甚至可能。
我是以错误的方式看待这个吗?
答案 0 :(得分:1)
所以我自己想出了这个...有趣的解决方案,所以我想我会为世界分享它。我最终使用了提供程序(ToProvider)
我的提供者实施:
public class ExecutorProvider : Provider<IDbExecutor>
{
private readonly string _connectoinString;
public ExecutorProvider(Func<string> connectionString)
{
_connectionString = connectionString();
}
protected override IDbExecutor CreateInstance(IContext context)
{
return new SqlExecutor(() => {
var sqlconnection = new SqlConnection(_connectionString);
sqlconnection.Open();
return sqlconnection;
});
}
}
然后我使用Lazy(T)创建了一个SqlExecutor的新实现,以便在使用时仅实例化并打开SqlConnection:
public class SqlExecutor : IDbExecutor
{
readonly Lazy<SqlConnection> _sqlConnection;
public SqlExecutor(Func<SqlConnection> sqlConnection)
{
_sqlConnection = new Lazy<SqlConnection>(() => sqlConnection());
}
public int Execute(
string sql,
object param = null,
IDbTransaction transaction = null,
int? commandTimeout = default(int?),
CommandType? commandType = default(CommandType?))
{
return _sqlConnection.Value.Execute(
sql,
param,
transaction,
commandTimeout,
commandType);
}
public IEnumerable<dynamic> Query(
string sql,
object param = null,
IDbTransaction transaction = null,
bool buffered = true,
int? commandTimeout = default(int?),
CommandType? commandType = default(CommandType?))
{
return _sqlConnection.Value.Query(
sql,
param,
transaction,
buffered,
commandTimeout,
commandType);
}
public IEnumerable<T> Query<T>(
string sql,
object param = null,
IDbTransaction transaction = null,
bool buffered = true,
int? commandTimeout = default(int?),
CommandType? commandType = default(CommandType?))
{
return _sqlConnection.Value.Query<T>(
sql,
param,
transaction,
buffered,
commandTimeout,
commandType);
}
public void Dispose()
{
_sqlConnection.Value.Dispose();
}
}
然后是我的约束力:
kernel.Bind<IDbExecutor>().ToProvider(new ExecutorProvider(()
=> connections["ProviderSearch"].ConnectionString))
.WhenTargetHas<BHNAttribute>()
.InRequestScope();
这允许我在注入我的实现类时执行此操作,以将注入的sql执行器与基于该属性的数据库连接相关联:
public class ProviderRepository : IProviderRepository
{
private readonly IDbExecutor executor;
public ProviderRepository([BHN]IDbExecutor executor)
{
this.executor = executor;
}
public IList<SearchType> GetAllSearchTypes()
{
return executor
.Query<SearchType>("pSEL_LU_SEARCHTYPE_Load", commandType: CommandType.StoredProcedure)
.ToList();
}
}
BHNAttribute([BHN])只是一个继承自Attribute的空类。
注意:是的我知道使用存储过程这是蹩脚的,但遗憾的是我的双手被绑在那个上。
我不想重新创建SqlExecutor类,但这非常有用。