Ninject 的 Dapper 一次性实例

Dapper disposable instance with Ninject

我想使用 Ninject 绑定数据库连接实例并在线程范围内使用它,以便在需要进行查询时跳过重复输入 using { var cn = new DbConnectionFactory() } [..]

我添加了绑定:

IOC.Kernel.Bind<IDbConnection>().ToMethod(ctx =>
{
    using (var cn = new DbConnectionFactory())
    {
        return cn.GetConnection();
    }
}).InThreadScope();

数据库工厂class:

public class DbConnectionFactory : IDisposable
{
    private IDbConnection _connection;

    public DbConnectionFactory()
    {
        _connection = new SQLiteConnection("Data Source=mydb.sqlite;Version=3;");
        _connection.Open();
    }

    public IDbConnection GetConnection() => _connection;

    public void Dispose()
    {
        _connection.Close();
    }
}

现在,一切正常。每个线程正在创建一个数据库连接,但是,连接正在关闭但未被释放!

所以当我修改我的 Dispose 方法时:

public void Dispose()
{
    _connection.Close();
    _connection.Dispose();
}

连接似乎不再正常工作,访问时抛出异常:ObjectDisposedException对象不再可访问。

问题是:如何在 Ninject 中正确绑定和处理连接?

请注意,我不能使用 .InRequestScope(),因为这不是 Web 应用程序。

对于 Ninject 和其他 IoC 容器,容器有责任在一次性对象上调用 Dispose。不幸的是,在您的实施中,您自己调用了 Dispose - 并且调用不正确。

using (var cn = new DbConnectionFactory())
{
    return cn.GetConnection();
}

此代码创建 DbConnectionFactory 并创建数据库连接。然后(由于 using)它调用 cn.Dispose。然后,您的实施会处理您 刚刚 创建的新连接。

有多种方法可以解决这个问题,但我建议您首先改变的是:

public class DbConnectionFactory
{
    public IDbConnection GetConnection() 
    {
        var connection = new SQLiteConnection("Data Source=mydb.sqlite;Version=3;");
        connection.Open();
        return connection;
    }
}

然后:

IOC.Kernel.Bind<IDbConnection>().ToMethod(ctx =>
{
    var cn = new DbConnectionFactory();
    return cn.GetConnection();
}).InThreadScope();

然后,根据 docs,当底层 Thread 被垃圾回收时,数据库连接将自动 Disposed。