Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/82.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# 在共享连接时正确重用SqlCommand和SqlParameter_C#_Sql_Sql Server_Ado.net - Fatal编程技术网

C# 在共享连接时正确重用SqlCommand和SqlParameter

C# 在共享连接时正确重用SqlCommand和SqlParameter,c#,sql,sql-server,ado.net,C#,Sql,Sql Server,Ado.net,我正在进行一个设置,其中一个可扩展的WCF服务组件连接到一个MS SQL Server数据库。RESTful服务允许用户将数据保存到数据库中并从中获取数据 在实现一个处理数据库连接/方法的类时,我开始努力正确地重用准备好的SqlCommands和连接。我阅读了MSDN中有关连接池的内容,以及如何使用SqlCommand和SqlParameter 该类的初始版本如下所示: public class SqlRepository : IDisposable { private object s

我正在进行一个设置,其中一个可扩展的WCF服务组件连接到一个MS SQL Server数据库。RESTful服务允许用户将数据保存到数据库中并从中获取数据

在实现一个处理数据库连接/方法的类时,我开始努力正确地重用准备好的
SqlCommands
和连接。我阅读了MSDN中有关连接池的内容,以及如何使用
SqlCommand
SqlParameter

该类的初始版本如下所示:

public class SqlRepository : IDisposable
{
    private object syncRoot = new object();

    private SqlConnection connection;

    private SqlCommand saveDataCommand;
    private SqlCommand getDataCommand;

    public SqlRepository(string connectionString)
    {
        // establish sql connection
        connection = new SqlConnection(connectionString);
        connection.Open();

        // save data
        saveDataCommand = new SqlCommand("INSERT INTO Table (Operation, CustomerId, Data, DataId, CreationDate, ExpirationDate) VALUES (@Operation, @CustomerId, @Data, @DataId, @CreationDate, @ExpirationDate)", connection);
        saveDataCommand.Parameters.Add(new SqlParameter("Operation", SqlDbType.NVarChar, 20));
        saveDataCommand.Parameters.Add(new SqlParameter("CustomerId", SqlDbType.NVarChar, 50));
        saveDataCommand.Parameters.Add(new SqlParameter("Data", SqlDbType.NVarChar, 50));
        saveDataCommand.Parameters.Add(new SqlParameter("DataId", SqlDbType.NVarChar, 50));
        saveDataCommand.Parameters.Add(new SqlParameter("CreationDate", SqlDbType.DateTime));
        saveDataCommand.Parameters.Add(new SqlParameter("ExpirationDate", SqlDbType.DateTime));
        saveDataCommand.Prepare();

        // get data
        getTripCommand = new SqlCommand("SELECT TOP 1 Data FROM Table WHERE CustomerId = @CustomerId AND DataId = @DataId AND ExpirationDate > @ExpirationDate ORDER BY CreationDate DESC", connection);
        getTripCommand.Parameters.Add(new SqlParameter("CustomerId", SqlDbType.NVarChar, 50));
        getTripCommand.Parameters.Add(new SqlParameter("DataId", SqlDbType.NVarChar, 50));
        getTripCommand.Parameters.Add(new SqlParameter("ExpirationDate", SqlDbType.DateTime));
        getTripCommand.Prepare();
    }

    public void SaveData(string customerId, string dataId, string operation, string data, DateTime expirationDate)
    {
        lock (syncRoot)
        {
            saveDataCommand.Parameters["Operation"].Value = operation;
            saveDataCommand.Parameters["CustomerId"].Value = customerId;
            saveDataCommand.Parameters["CreationDate"].Value = DateTime.UtcNow;
            saveDataCommand.Parameters["ExpirationDate"].Value = expirationDate;
            saveDataCommand.Parameters["Data"].Value = data;
            saveDataCommand.Parameters["DataId"].Value = dataId;

            saveDataCommand.ExecuteNonQuery();
        }
    }

    public string GetData(string customerId, string dataId)
    {
        lock (syncRoot)
        {
            getDataCommand.Parameters["CustomerId"].Value = customerId;
            getDataCommand.Parameters["DataId"].Value = dataId;
            getDataCommand.Parameters["ExpirationDate"].Value = DateTime.UtcNow;

            using (var reader = getDataCommand.ExecuteReader())
            {
                if (reader.Read())
                {
                    string data = reader.GetFieldValue<string>(0);
                    return data;
                }
                else
                {
                    return null;
                }
            }
        }
    }

    public void Dispose()
    {
        try
        {
            if (connection != null)
            {
                connection.Close();
                connection.Dispose();
            }

            DisposeCommand(saveDataCommand);
            DisposeCommand(getDataCommand);
        }
        catch { }
    }

    private void DisposeCommand(SqlCommand command)
    {
        try
        {
            command.Dispose();
        }
        catch (Exception)
        {
        }
    }
}
公共类SqlRepository:IDisposable { 私有对象syncRoot=新对象(); 专用SqlConnection; 私有SqlCommand-saveDataCommand; 私有SqlCommand-getDataCommand; 公共SqlRepository(字符串连接字符串) { //建立sql连接 连接=新的SqlConnection(connectionString); connection.Open(); //保存数据 saveDataCommand=new-SqlCommand(“插入表(操作、客户ID、数据、数据ID、CreationDate、ExpirationDate)值(@Operation、@CustomerId、@Data、@DataId、@CreationDate、@ExpirationDate)”,连接); saveDataCommand.Parameters.Add(新的SqlParameter(“Operation”,SqlDbType.NVarChar,20)); saveDataCommand.Parameters.Add(新的SqlParameter(“CustomerId”,SqlDbType.NVarChar,50)); saveDataCommand.Parameters.Add(新的SqlParameter(“Data”,SqlDbType.NVarChar,50)); saveDataCommand.Parameters.Add(新的SqlParameter(“DataId”,SqlDbType.NVarChar,50)); saveDataCommand.Parameters.Add(新的SqlParameter(“CreationDate”,SqlDbType.DateTime)); saveDataCommand.Parameters.Add(新的SqlParameter(“ExpirationDate”,SqlDbType.DateTime)); saveDataCommand.Prepare(); //获取数据 getTripCommand=new SqlCommand(“从CustomerId=@CustomerId和DataId=@DataId和ExpirationDate>@ExpirationDate ORDER BY CreationDate DESC”连接的表中选择前1位数据); 添加(新的SqlParameter(“CustomerId”,SqlDbType.NVarChar,50)); 添加(新的SqlParameter(“DataId”,SqlDbType.NVarChar,50)); 添加(新的SqlParameter(“ExpirationDate”,SqlDbType.DateTime)); getTripCommand.Prepare(); } public void SaveData(字符串customerId、字符串dataId、字符串操作、字符串数据、DateTime expirationDate) { 锁定(同步根) { saveDataCommand.Parameters[“Operation”]。值=操作; saveDataCommand.Parameters[“CustomerId”]。值=CustomerId; saveDataCommand.Parameters[“CreationDate”]。Value=DateTime.UtcNow; saveDataCommand.Parameters[“ExpirationDate”]。值=ExpirationDate; saveDataCommand.Parameters[“Data”]。值=数据; saveDataCommand.Parameters[“DataId”]。值=DataId; saveDataCommand.ExecuteOnQuery(); } } 公共字符串GetData(字符串customerId、字符串dataId) { 锁定(同步根) { getDataCommand.Parameters[“CustomerId”]。值=CustomerId; getDataCommand.Parameters[“DataId”]。值=DataId; getDataCommand.Parameters[“ExpirationDate”]。值=DateTime.UtcNow; 使用(var reader=getDataCommand.ExecuteReader()) { if(reader.Read()) { 字符串数据=reader.GetFieldValue(0); 返回数据; } 其他的 { 返回null; } } } } 公共空间处置() { 尝试 { if(连接!=null) { connection.Close(); connection.Dispose(); } DisposeCommand(saveDataCommand); DisposeCommand(getDataCommand); } 捕获{} } 私有void DisposeCommand(SqlCommand) { 尝试 { command.Dispose(); } 捕获(例外) { } } } 有几个方面需要了解:

  • 我正在使用
    SqlCommand.Prepare()
    来加速执行命令的过程
  • 重用这些命令可以避免在每次调用GetData和SaveData方法时创建新对象,从而不会导致垃圾收集器出现问题
  • WCF服务只使用了
    SqlRepository
    类的一个实例
  • 这项服务每分钟有许多呼叫,因此我想要保持与DB的连接打开
现在我读了更多关于连接池的内容,以及强烈建议在
using
语句中使用
SqlConnection
对象以确保处理的事实。据我所知,连接池技术负责保持连接打开,即使
using
语句调用了
SqlConnection
Dispose()
方法

使用这种方法的方法是在
GetData
SaveData
方法中使用(SqlConnection connection=newsqlconnection(connectionString))。然而,至少在我的直觉看来,我还需要在
GetData
/
SaveData
方法中创建SqlCommands。还是不?我找不到任何关于如何以这种方式重用命令的文档。如果每次进入
GetData
/
SaveData
方法时都需要准备一个新命令,那么对
SqlCommand.Prepare()
的调用不是毫无意义吗

如何正确实现
SqlRepository
类?现在的情况是,我相信如果连接中断(可能是因为DB服务器坏了)