Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/339.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 保持数据库连接打开?_C#_Sql Server_Sqlite_Unit Testing_Unity Container - Fatal编程技术网

C# 保持数据库连接打开?

C# 保持数据库连接打开?,c#,sql-server,sqlite,unit-testing,unity-container,C#,Sql Server,Sqlite,Unit Testing,Unity Container,我的web应用程序具有以下类: public class DatabaseProvider { private readonly IDbConnection _cn; public DatabaseProvider(IDbConnection cn) { _cn = cn; } public void ExecuteNonQuery(string query) { // Execute the query var

我的web应用程序具有以下类:

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();
    }
}
其中,IDbConnection依赖项是使用以下代码(使用Microsoft Unity)声明的:

container.RegisterType(新注入工厂(c=>{
var cn=新的SqlConnection(“…”);
cn.Open();
返回cn;
}));
这允许我交换到SQLite的连接,如下所示:

container.RegisterType<IDbConnection>(new InjectionFactory(c => {
    var cn = new SQLiteConnection("Data Source=:memory:;Version=3;");
    cn.Open();
    return cn;
}));
container.RegisterType(新注入工厂(c=>{
var cn=new-SQLiteConnection(“数据源=:内存:;版本=3;”;
cn.Open();
返回cn;
}));
我在测试时使用SQLite,连接必须保持打开状态,否则数据会丢失。因此,我不能在需要时打开和关闭连接

我总是在需要时打开与数据库的连接,我想知道这是否可以扩展到大型应用程序


如果您能就如何改进这一点提出建议,我将不胜感激。谢谢,作为ADO.NET中的一般规则,必须尽快关闭连接

连接从连接池中重复使用,是稀缺资源

推荐的方法是使用(){}构造

我们强烈建议您在使用完毕后始终关闭连接,以便连接将返回到池中。您可以使用Connection对象的Close或Dispose方法,或者通过打开C#中的using语句或Visual Basic中的using语句中的所有连接来完成此操作。未显式关闭的连接可能不会添加或返回到池中。有关详细信息,请参见使用语句(C#引用)或如何:为Visual Basic处置系统资源(Visual Basic)


因此,我建议您创建一个接口IDbProvider,然后创建两个实现:SqlServerProviderSQLiteProvider,并处理它们内部的打开和关闭连接。然后使用Unity绑定一个或另一个提供程序。

在Unity中实例化连接时不要打开它。但是,像往常一样,在第一次在代码中使用时打开它,在不再需要时关闭它

这将更改数据库提供程序

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用于创建实例的范围和跨越的生存期。
上面的解决方案不是线程安全的,在不同的线程上有相同的实例可以带来一个很好的调试fest。

您也可以检查这个

以我的方式,总是检查连接状态,当它打开时关闭它

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
            }

        }


    }
}

谢谢你的回答。我把Petar的答案打上了记号,因为它提供了更多的细节。谢谢,这大概就是我的想法。@Petar Repac,你能告诉我为什么你说连接是稀缺资源吗?这是什么意思?谢谢。@dan,创建到DB的新连接的成本很高(需要与DB协商各种细节),正因为如此,.NET保留了一个已创建连接的“池”,以便您的代码可以重用池中的一个连接,而不是总是创建一个新的连接。但是您的代码必须表现良好,并且在使用DB之后,必须将连接返回到池中。@Petar Repac,感谢您的澄清。所以,当你说连接创建是昂贵的,这不意味着离开开放的连接是非常明智的吗?我之前关于“连接是恐惧资源”的问题就是关于这一点的。再次感谢并非常感谢您对此的想法。
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
            }

        }


    }
}