我想使用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应用程序。
答案 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
。