簡體   English   中英

如何在C#.net中使用事務

[英]How to use transaction in C#.net

我想以很高的速度將數據插入sqlserver。 因此,我在c#.net中使用事務,但是在使用事務之后,我注意到插入速度與不使用它沒有區別。 請檢查我的代碼並幫助我解決它。

代碼:

void ReadToTable()
    {

        try
        {
            if (dir != "")
            {
                dic.Clear();
                string[] lines = System.IO.File.ReadAllLines(dir);
                foreach (string line in lines)
                {
                    SqlConnection sqlconn = new SqlConnection(DBsetting.Connstring);
                    sqlconn.Open();
                    SqlTransaction transaction = sqlconn.BeginTransaction();
                    if (!string.IsNullOrEmpty(line))
                    {
                        l = line.Split('\t');
                        l[0] = l[0].Trim();
                        l[1] = l[1].Trim();
                        l[2] = l[2].Trim();
                        l[3] = l[3].Trim();
                        if (!string.IsNullOrEmpty(l[0]) && l[3] == "1" || l[3] == "0")
                        {
                            dic.Add(new KeyValuePair<string, string>(l[0], l[1]));
                            PersianCalendar persCal = new PersianCalendar();
                            SqlCommand sqlda = new SqlCommand("insert into readd(IDp,date,day,nobatkari)values(@IDp,@date,@day,@nobatkari)", sqlconn, transaction);
                            sqlda.Transaction = transaction;
                            sqlda.Parameters.AddWithValue("@date", l[1]);
                            sqlda.Parameters.AddWithValue("@IDp", l[0]);
                            sqlda.Parameters.AddWithValue("@day", GetDayOfWeek(GetPerDate(l[1])));
                            sqlda.Parameters.AddWithValue("@nobatkari", "");//ntkari[idx].ToString());
                            sqlda.ExecuteNonQuery();
                            transaction.Commit();
                            sqlconn.Close();
                            sqlconn.Dispose();

                        }
                        else
                        {
                            ReadDataAndInsertIntoTable(line);
                        }
                    }

                }
                RefGrid();
                foreach (var pair in dic)
                {
                    InsertNobatKari(pair.Key, GetPerDate(pair.Value).ToString());
                }
            }

        }
        catch (Exception ex)
        {
            if (ex.Message.Contains("there is no row at position 0"))
            {
                MessageBox.Show("لطفا سطر خالی را انتخاب ننمایید");
            }
            else if (ex.Message.Contains("Cannot insert duplicate key row in object"))
            {
                MessageBox.Show("امکان ورود سطر تکراری وجود ندارد");
            }
            else
            {
                MessageBox.Show(ex.Message);
            }
        }
        finally
        {

        }
    }

我想以很高的速度將數據插入sqlserver。因此我在c#.net中使用事務,但是在使用事務后,我注意到插入速度與不使用它沒有區別。

是的,您不會看到改善,因為交易不是為了提高速度。 另外,您沒有正確使用事務:您沒有提交事務。


您的方法

想想你在做什么。 您正在循環一個文件中的行,並為每一行創建一個數據庫連接,然后一直到數據庫插入一條記錄。 您執行n次,其中n是您的文本文件中的記錄數。

另一件事是您正在使用File.ReadAllLines ,它將把整個文件讀入內存:如果文件真的很大怎么辦? 你的記憶能應付嗎?


更好的方法

更好的方法是創建一個連接,然后轉到數據庫並獲取一批記錄(50、100或更多),然后一次完成。 繼續執行此操作,直到所有記錄都輸入為止。

另外,您應該使用File.ReadLines以便它會延遲讀取每一行(一旦被請求,它將把該行加載到內存中)。

要提高速度,請使用SqlBulkCopy 確保您閱讀了有關列映射的部分。

腳步:

  1. 從文件中讀取一行。
  2. 在這一行的基礎上,創建您的內存表結構。

     string[] strArray = line.Split('\\t'); var dt = new DataTable(); for (int index = 0; index < strArray.Length; index++) dt.Columns.Add(new DataColumn()); 
  3. 從文件填充內存數據表:

     do { DataRow row = dt.NewRow(); string[] itemArray = line.Split('\\t'); row.ItemArray = itemArray; dt.Rows.Add(row); i = i + 1; line = sr.ReadLine(); } while (!string.IsNullOrEmpty(line)); 
  4. 將數據發送到數據庫:

     var bc = new SqlBulkCopy(dbConn, SqlBulkCopyOptions.TableLock, null) { DestinationTableName = "TestData", BatchSize = dt.Rows.Count }; dbConn.Open(); bc.WriteToServer(dt); dbConn.Close(); bc.Close(); 

如果文件很大,則可以分批執行步驟4。 在上面的代碼中, sr變量將是StreamReader一個實例,但是無論如何您都可以使用它來讀取文件。


注意:

此代碼不可復制粘貼,而只是作為指導,因此您需要對其進行調整以適合您的需求。

您為插入的每行創建一個事務,這與不進行事務的所有操作幾乎相同。 您可能應該執行以下操作:

    string[] lines = System.IO.File.ReadAllLines(dir);
    SqlConnection sqlconn = new SqlConnection(DBsetting.Connstring);
    sqlconn.Open();
    SqlTransaction transaction = sqlconn.BeginTransaction();
    foreach (string line in lines)
    {
        ...
    }
    transaction.Commit();
    sqlconn.Close();
    sqlconn.Dispose();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM