1

我正在尝试创建一些“存储库”样式类来包装通过 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 的使用,就像我之前做的那样. 或者,如果这在这一点上是可能的。

我看错了吗?

4

1 回答 1

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 类,但这非常有效。

于 2013-11-08T20:39:39.310 回答