我的网络应用程序有以下类:
public class DatabaseProvider {
private readonly IDbConnection _cn;
public DatabaseProvider(IDbConnection cn) {
_cn = cn;
}
public void ExecuteNonQuery(string query) {
// Execute the query
var cmd = _cn.CreateCommand();
cmd.CommandText = query;
cmd.ExecuteNonQuery();
}
}
使用以下代码(使用Microsoft Unity)声明IDbConnection依赖项:
container.RegisterType<IDbConnection>(new InjectionFactory(c => {
var cn = new SqlConnection("...");
cn.Open();
return cn;
}));
这允许我像这样交换到SQLite的连接:
container.RegisterType<IDbConnection>(new InjectionFactory(c => {
var cn = new SQLiteConnection("Data Source=:memory:;Version=3;");
cn.Open();
return cn;
}));
我在测试时使用SQLite,连接必须保持打开,否则数据会丢失。因此,我不能在需要时打开和关闭连接。
我总是在需要时打开与数据库的连接,并想知道这是否会扩展到大型应用程序?
我很欣赏有关如何改进的建议。感谢
答案 0 :(得分:5)
作为ADO.NET的一般规则,必须尽快关闭连接。
连接从连接池重用,并且是稀缺资源。
建议的方法是使用using(){}构造。
SQL Server Connection Pooling (ADO.NET)
我们强烈建议您在完成使用后始终关闭连接,以便连接将返回到池。您可以使用Connection对象的Close或Dispose方法,或打开 a C#中的using语句或Visual Basic中的Using语句中的所有连接来执行此操作。未显式关闭的连接可能不会添加或返回到池中。有关更多信息,请参阅使用语句(C#参考)或如何:为Visual Basic处理系统资源(Visual Basic)。
所以,我建议您创建一个接口 IDbProvider 然后进行2次实现: SqlServerProvider 和 SQLiteProvider 并处理内部的打开和关闭连接他们。然后使用Unity绑定一个或另一个提供者。
答案 1 :(得分:0)
在以单位形式实例化连接时,请勿打开它。但是,像往常一样在代码中首次使用时打开它,并在不再需要时关闭它。
这会改变您的DatabaseProvider
public class DatabaseProvider {
private readonly IDbConnection _cn;
public DatabaseProvider(IDbConnection cn) {
_cn = cn;
}
public void ExecuteNonQuery(string query) {
// Execute the query
try{
_cn.Open();
var cmd = _cn.CreateCommand();
cmd.CommandText = query;
cmd.ExecuteNonQuery();
}
catch(ExpectedExceptions){
//take care of business
}
finally{
_cn.Close();
}
}
}
请注意Unity用于创建实例和跨越生命周期的范围。 上面的解决方案不是线程安全的,在不同的线程上使用相同的实例可以带来一个很好的调试功能。
答案 2 :(得分:0)
您也可以查看此内容。
以我的方式总是检查连接状态以及何时打开它。
public class DatabaseProvider {
private readonly IDbConnection _cn;
public DatabaseProvider(IDbConnection cn) {
_cn = cn;
}
public void ExecuteNonQuery(string query) {
using(SqliteCommand cmd = new SqliteCommand{ Connection = _cn})
{
if(_cn.State == ConnectionState.Open)
_cn.Close();
try
{
_cn.Open();
}
catch
{
// Message Connection Error
}
try
{
cmd.CommandText = query;
cmd.ExecuteNonQuery();
}
catch
{
// Message Query Error
}
finally
{
_cn.Close(); // Connection close
}
}
}
}