C#连接SQL Server数据库,并解决 “已有打开的与此 Command 相关联的 DataReader,必须首先将它关闭”

C#连接SQL Server数据库,并解决 “已有打开的与此 Command 相关联的 DataReader,必须首先将它关闭”

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Data;
using System.Data.SqlClient;

namespace demoConnectOperation
{
    class Program
    {
        static void Main(string[] args)
        {
            //连接数据库
            SqlConnectionStringBuilder scsb = new SqlConnectionStringBuilder();
            scsb.DataSource = "127.0.0.1";
            scsb.UserID = "sa";
            scsb.Password = "playea";
            scsb.InitialCatalog = "stu_db";
            scsb.MultipleActiveResultSets = true;//解决已有打开的与此 Command 相关联的 DataReader,必须首先将它关闭。

            //创建连接
            SqlConnection conn = new SqlConnection(scsb.ToString());

            //打开连接
            if (conn.State == ConnectionState.Closed)
            {
                conn.Open();
            }

            //定义变量
            string stu_Number = null;
            string stu_Class=null;
            string stu_Name=null;
            string stu_Sex=null;
            string stu_Age = null;
            bool isFlag = false;

            while (true)
            {
                Console.WriteLine("插入信息【1】;修改信息【2】;删除信息【3】,请输入你要的操作:");
                int choice = int.Parse(Console.ReadLine());

                switch (choice)
                {
                    case 1:
                        //插入学生信息
                        //'学号','班级','姓名','性别','年龄'
                        Console.WriteLine("请输入学号:");
                        stu_Number = Console.ReadLine();
                        Console.WriteLine("请输入班级:");
                        stu_Class = Console.ReadLine();

                        //根据学号和班级判断,学生信息是否存在
                        isFlag = ExistsStu(conn, stu_Number, stu_Class);
                        if (isFlag)
                        {
                            Console.WriteLine("输入的学生信息已经存在!");
                            break;
                        }

                        Console.WriteLine("请输入姓名:");
                        stu_Name = Console.ReadLine();
                        Console.WriteLine("请输入性别:");
                        stu_Sex = Console.ReadLine();
                        Console.WriteLine("请输入年龄:");
                        stu_Age = Console.ReadLine();

                        //在SQL server数据库中添加信息
                        //添加数据的操作
                        string strInsert = "INSERT INTO [stu_db].[dbo].[Students]([stuNumber],[stuClass],[stuName],[stuSex],[stuAge])"
                           + "VALUES('" + stu_Number + "','" + stu_Class + "','" + stu_Name + "','" + stu_Sex + "','" + stu_Age + "')";

                        //进行数据库操作
                        sqlChoice(strInsert, conn);
                        break;
                    case 2:
                        //修改学生信息
                        //'学号','班级','姓名','性别','年龄'
                        Console.WriteLine("请输入学号:");
                        stu_Number = Console.ReadLine();
                        Console.WriteLine("请输入班级:");
                        stu_Class = Console.ReadLine();

                        //根据学号和班级判断,学生信息是否存在
                        isFlag = ExistsStu(conn, stu_Number, stu_Class);
                        if (!isFlag)
                        {
                            Console.WriteLine("输入的学生信息不存在!");
                            break;
                        }

                        Console.WriteLine("请输入姓名:");
                        stu_Name = Console.ReadLine();
                        Console.WriteLine("请输入性别:");
                        stu_Sex = Console.ReadLine();
                        Console.WriteLine("请输入年龄:");
                        stu_Age = Console.ReadLine();

                        //根据学号和班级更改 信息
                        string strUpdate = "UPDATE [stu_db].[dbo].[Students] SET [stuNumber] = '" + stu_Number + "',[stuClass] = '" + stu_Class
                             + "',[stuName] = '" + stu_Name + "',[stuSex] = '" + stu_Sex + "',[stuAge] = '" + stu_Age + "' WHERE stuNumber='" + stu_Number + "' AND stuClass='" + stu_Class + "'";

                        //进行操作
                        sqlChoice(strUpdate, conn);
                        break;
                    case 3:

                        //根据学号和班级进行删除
                        Console.WriteLine("请输入学号:");
                        stu_Number = Console.ReadLine();
                        Console.WriteLine("请输入班级:");
                        stu_Class = Console.ReadLine();

                        //根据学号和班级判断,学生信息是否存在
                        isFlag = ExistsStu(conn, stu_Number, stu_Class);
                        if (!isFlag)
                        {
                            Console.WriteLine("输入的学生信息不存在!");
                            break;
                        }

                        //删除
                        string sqlDelete = "DELETE FROM [stu_db].[dbo].[Students]WHERE stuNumber='" + stu_Number + "' AND stuClass='" + stu_Class + "'";

                        //进行操作
                        sqlChoice(sqlDelete, conn);

                        break;
                    default:
                        Console.WriteLine("输入操作指令有误!");
                        break;
                }

            }
        }

        //执行数据库语句操作
        public static void sqlChoice(string sqlString,SqlConnection conn)
        {
            //输出测试
            Console.WriteLine("SQL插入语句:");
            Console.WriteLine(sqlString);
           
            //连接数据表
            SqlCommand comm = new SqlCommand(sqlString, conn);

            try
            {
                int rc = comm.ExecuteNonQuery();
                if (rc == 1)
                {
                    Console.WriteLine("学员信息操作成功!");
                }
                else
                {
                    Console.WriteLine("学员信息操作失败!");
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }

        }

        
        //判断用户输入学生信息是否存在
        public static bool ExistsStu(SqlConnection conn,string stu_Number,string stu_Class) {
            //sql语句
            string sqlSelect = "SELECT *FROM [stu_db].[dbo].[Students]WHERE stuNumber='" + stu_Number + "' AND stuClass='" + stu_Class + "'";
            
            //执行操作
            //连接数据表
            SqlCommand comm = new SqlCommand(sqlSelect, conn);

            SqlDataReader dr = comm.ExecuteReader();

            return dr.Read();
            
        }




    }
}

  

qlCommand在每次执行ExecuteNonQuery()方法之后,内部会生成一个空的DataReader对象,该对象只有在数据库连接关闭之后,才会被释放掉,加上上边提到的,在DBHelper类中数据库连接对象是一个静态的全局变量。因为在同时调用API进行数据查询时,在第一个查询还未结束,数据库连接对象还未关闭,第二个查询却已经开始查询,所以才会出现DataReader没有关闭的情况

方法有三:

第一种方法:

使用using的形式:

Using(SqlConnection sqlConn=new  SqlConnection(“数据库连接字符串”)

{

sqlConn.Open();

SqlCommand com=new SqlCommnand(sqlCon,”sql”);

/执行访问数据库操作代码

}

Using指定了SqlConnection的对象作用的范围,且是独占使用的,当使用结束之后会自动将其进行释放,所以也就很好的解决了上边的问题,即使是同时多次访问,也不会有DataReader未关闭的情况,因为只有一次访问完,释放之后才会进行下一次的访问。

第二中方法:

在数据库连接字符串中添加MultipleActiveResultSets=true即可,示例如下:

server=.;Integrated Security = true;database=Test;MultipleActiveResultSets=true;

SQL Server数据库默认的只有一个活动的SqlDataReader,如果想要一个连接允许多个SqlDataReader,那就需要将MultipleActiveResultSets设置为true,其意义为:将数据库连接设置可复用,即可供多个SqlCommand同时使用。

如果在 MARS 连接下提交两个批处理,一个批处理包含 SELECT 语句,另一个包含 DML 语句,DML 可以在 SELECT 语句执行过程中开始执行。 但是,DML 语句必须运行完成,SELECT 语句才可以继续执行。 如果两个语句在相同事务下运行,读取操作将看不到 DML 语句在 SELECT 语句开始执行后所作的任何更改。

如果打开了启用了MARS会话连接,会创建一个逻辑会话,增加系统的开销,为了减小系统开销提升系统性能,SqlClient会将对MARS对话缓存在连接内,做多可缓存10个对话。

MARS的操作不是线程安全的。如果应用程序打开了两个连接一个为MARS连接一个为一般连接,则这两个连接分别位于独立的连接池中。使用MARS之后,并非不再需要在应用程序中使用多个连接,如果应用程序需要对服务器真正的执行并行命令,还是需要建立多个连接的。

所以,总的来说,虽然这种方法很简单,也能解决问题,但是还是不推荐使用这种方法的。

第三种方法:

之所以会出现上边报出的错误,往往都是因为数据连接对象是静态、全局的对象,相应有很多朋友为了避免多次的声明、创建对象,干脆将该数据连接对象设置为静态的全局的,这样做的确可以省下不少的功夫,但是带来的弊端也是显而易见的,也就是再高并发操作的情况下,会出现上边提到的错误。

因此,这里建议,将数据连接对象设置为局部的,且每次都new一个对象出来,这样做不过是多创建了几个对象,开了几个连接罢了,但是,即使是高并发也不会出现DataReader未关闭的情况。此外,事实上只有在第一次进行数据连接比较耗费时间和性能之外,以后进行的连接操作,所耗费的时间几乎是可以忽略不计的,因为SqlConnection还有连接池的机制,这也是下边要讲的一个内容。
————————————————
原文链接:https://blog.csdn.net/abrahamchen/article/details/86647978

猜你喜欢

转载自www.cnblogs.com/domefy/p/12173436.html