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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM