System.InvalidOperationException - >与此命令关联的DataReader [事务失败提交]

时间:2018-06-04 12:30:24

标签: c# sql-server

我有这样的问题。我已经将Transaction服务添加到我的SQL类中。当我想在执行后提交查询时,我收到错误。我将粘贴代码:

//SOME OF VARIABLES IN CLASS:
private SqlConnection connection;
private SqlCommand newQuery;
private SqlTransaction transaction;
private SqlDataReader result;

//BEGINNING TRANSACTION
public void BeginTransaction(string name)
{
    try
    {
        transaction = connection.BeginTransaction(name);
    }

    catch
    {
        MessageBox.Show("Error while beginning transaction " + name);
    }
}

//COMMIT TRANSACTION
public void Commit(string text)
{
    try
    {
        transaction.Commit();
    }

    catch (Exception e)
    {
        MessageBox.Show("Couldn't commit transaction " + text + "\n\n" + e.ToString());

        try
        {
            transaction.Rollback();
        }

        catch
        {
            MessageBox.Show("Couldn't Rollback transaction " + text);
        }
    }

        transaction = null;
}

//EXECUTE QUERY METHOD
private SqlDataReader ExecuteQuery(string query)
{
    try
    {
        if (connection.State == ConnectionState.Closed)
            connection.Open();

        if (result != null)
            result.Close();

        newQuery = connection.CreateCommand();
        newQuery.CommandText = query;
        newQuery.Transaction = transaction;

        result = newQuery.ExecuteReader();
    }

    catch (Exception e)
    {
        MessageBox.Show(e.ToString());
    }

    return result;
}

//EXAMPLE FUNCTION WITH TRANSACTION, WHICH OCCURS ERROR:
public bool DoesDatabaseExist(string dbName)
{
    BeginTransaction("DoesDatabaseExist");
    bool res = ExecuteQuery("SELECT * FROM master.dbo.sysdatabases WHERE name='" + dbName + "';").HasRows;
    Commit("Does DB Exist 211");

    return res;
}

Afrer运行程序,我收到错误,提交没有通过。像:

  

无法提交事务DB是否存在211

     

System.InvalidOperationException:已经有一个与此命令关联的打开的DataReader,必须先关闭它。

我正在学习C#中的编程,所以可能很容易识别错误。但不适合我。请帮忙。

在我添加交易服务之前,一切正常,我没有更改或添加任何查询或执行查询。请帮忙。

谢谢,迈克。

1 个答案:

答案 0 :(得分:1)

主要问题是您使用SqlDataReader个实例的方式。

你的第一个错误就是让它成为班上的一个领域:

private SqlDataReader result;

不要这样做(请删除该行)。

然后将功能更改为:

private SqlDataReader ExecuteQuery(string query)
{
    try
    {
        if (connection.State == ConnectionState.Closed)
            connection.Open();

        newQuery = connection.CreateCommand();
        newQuery.CommandText = query;
        newQuery.Transaction = transaction;

        var result = newQuery.ExecuteReader();
        return result;
    }

    catch (Exception e)
    {
        MessageBox.Show(e.ToString());
        throw;
    }
}

这确保了上述函数的每次调用都返回其自己的SqlDataReader

实例

好的,现在是来电者。您目前正在使用:

bool res = ExecuteQuery("SELECT * FROM master.dbo.sysdatabases WHERE name='" + dbName + "';").HasRows;
Commit("Does DB Exist 211");

这是不正确的,因为ExecuteQuery返回的SqlDataReader表示您没有正确清理。将其更改为:

var results = ExecuteQuery("SELECT * FROM master.dbo.sysdatabases WHERE name='" + dbName + "';");
using (results)
{
    bool res = results.HasRows;
}
Commit("Does DB Exist 211");

using将确保SqlDataReader正确处理(关闭)。

请注意,您的代码中仍有许多其他问题。例如:

  • 您对显式事务的使用毫无意义,因为您正在执行单个SELECT语句
  • 你的其他字段(用于命令,连接和交易)也是一个坏主意(如result是)
  • 您的代码向SQL Injection
  • 开放
  • 您可能希望阅读Dapper