C# 应用程序上的并发用户导致MySQL数据库错误

C# 应用程序上的并发用户导致MySQL数据库错误,c#,mysql,multiple-users,C#,Mysql,Multiple Users,我有一个连接到MySQL数据库的C#web应用程序。当多个用户同时访问站点时,我们会看到一个“已经有一个打开的datareader与此命令关联,必须先关闭”错误。当只有一个人访问站点时,应用程序工作正常 我在连接字符串中发现多篇文章的站点MultipleActiveResultSets=True,但这只适用于SQL Server,而不适用于MySql 我将错误追溯到我的runSQL函数,该函数处理我的大部分数据库查询,但找不到解决方案 这是一个相当直接的函数,它需要原始sql代码、参数列表、转换

我有一个连接到MySQL数据库的C#web应用程序。当多个用户同时访问站点时,我们会看到一个“已经有一个打开的datareader与此命令关联,必须先关闭”错误。当只有一个人访问站点时,应用程序工作正常

我在连接字符串中发现多篇文章的站点MultipleActiveResultSets=True,但这只适用于SQL Server,而不适用于MySql

我将错误追溯到我的runSQL函数,该函数处理我的大部分数据库查询,但找不到解决方案

这是一个相当直接的函数,它需要原始sql代码、参数列表、转换为许多可能的数据库连接字符串之一的枚举,以及确定是否需要设置事务的bool

我不知所措

public DataTable runSQL(string QueryStr, List<MySqlParameter> Parameters, ConnectionType Connection, bool Transaction)
{
    DataTable results = new DataTable();
    MySqlConnection con = new MySqlConnection(getConnection(Connection));
    MySqlTransation trans;
    MySqlCommand command;

    con.Open();

    //if a transaction was requested, tie one to the query
    if(Transaction)
    {
        trans = con.BeginTransaction();
        command = new MySqlCommand(QueryStr, con, trans);
    }
    else
    {
        command = new MySqlCommand(QueryStr, con);
    }

    //if parameters were provided add them to the query
    if(Parameters.Count > 0)
        foreach(MySqlParameter parm in Parameters)
            command.Parameters.Add(parm);

    try
    {
        //send the command and get the results
        MySqlReader rdr = command.ExecureReader();

        //populate the column names
        string columnName;
        Type type;
        foreach(DataViewRow row in rdr.GetSchemaTable().DefaultView)
        {
            columnName = row["ColumnName"].ToString();
            type = (Type)row["DataType"];
            results.Columns.Add(columnName, type);
        }

        //populate the results
        results.Load(rdr);

        //so far so good, close the transaction if one was requested
        if(Transaction)
        {
            command.Transaction.Commit();
        }

        con.Close();
    }
    catch (Exception up)
    {
        //something bad happened, rollback if there was a transaction
        if(Transaction)
        {
            command.Transaction.Rollback();
        }

        con.Close();

        //report the error for handling at source.
        throw up;
    }

    return results;
}
公共数据表runSQL(字符串QueryStr、列表参数、连接类型Connection、bool事务)
{
DataTable结果=新DataTable();
MySqlConnection con=新的MySqlConnection(getConnection(Connection));
mysqltransaction-trans;
MySqlCommand命令;
con.Open();
//如果请求了事务,则将一个事务绑定到查询
如果(交易)
{
trans=con.BeginTransaction();
command=新的MySqlCommand(QueryStr、con、trans);
}
其他的
{
command=新的MySqlCommand(QueryStr,con);
}
//如果提供了参数,则将其添加到查询中
如果(Parameters.Count>0)
foreach(MySqlParameter参数中的parm)
command.Parameters.Add(parm);
尝试
{
//发送命令并获取结果
MySqlReader rdr=command.ExecureReader();
//填充列名
字符串列名;
类型;
foreach(rdr.GetSchemaTable().DefaultView中的DataViewRow行)
{
columnName=行[“columnName”]。ToString();
类型=(类型)行[“数据类型”];
results.Columns.Add(columnName,type);
}
//填充结果
结果:负荷(rdr);
//到目前为止还不错,如果有人要求,请关闭交易
如果(交易)
{
command.Transaction.Commit();
}
con.Close();
}
赶上(例外情况)
{
//发生了不好的情况,如果有事务,请回滚
如果(交易)
{
command.Transaction.Rollback();
}
con.Close();
//报告错误以在源位置进行处理。
呕吐;
}
返回结果;
}

MySql中的并发是一场噩梦。很抱歉这样开始,但如果可能的话,您应该移植到MSSQL,因为您使用的是c#,并且它很容易集成

当使用MyISAM MySQL数据库引擎时,并发性特别差。首先,一个很大的危险信号是MyISAM不支持事务。这意味着您无法更改任何读取或更新的隔离级别。其次,与第一个相关的是,在表上使用read会发出低级表锁。但是,为了使更新发生,它必须有一个独占表锁,其他任何东西(即使是低级别的)都会阻止这种情况发生,并且它将进入锁队列

没有办法解决这个问题,因为它是经过设计的。

谢谢特拉维斯

我只是通过将函数设置为静态并从数据库连接中删除singleton模式来解决这个问题。我这样做是为了节省内存,但在这种情况下,它造成的问题比它解决的问题还多