Ninject的Dapper一次性实例

时间:2018-06-08 09:32:30

标签: c# sqlite ninject dapper dispose

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

我添加了一个绑定:

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

db工厂类:

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应用程序。

1 个答案:

答案 0 :(得分:3)

使用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,当基础Dispose被垃圾收集时,数据库连接将自动Thread