简体   繁体   English

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

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

I want to insert data into sqlserver with very high speed. 我想以很高的速度将数据插入sqlserver。 So, I Use transaction in c#.net but after use transaction I noticed that the speed of insertion has no difference with not using it. 因此,我在c#.net中使用事务,但是在使用事务之后,我注意到插入速度与不使用它没有区别。 Please check my code and help me to solve it. 请检查我的代码并帮助我解决它。

code : 代码:

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
        {

        }
    }

I want to insert data into sqlserver with very high speed .so I Use transaction in c#.net but after use transaction I noticed that the speed of insertion has no difference with not using it. 我想以很高的速度将数据插入sqlserver。因此我在c#.net中使用事务,但是在使用事务后,我注意到插入速度与不使用它没有区别。

YES you will not see improvement because transactions are not for improving speed. 是的,您不会看到改善,因为交易不是为了提高速度。 Plus you are not using transaction correctly: you are not committing the transaction. 另外,您没有正确使用事务:您没有提交事务。


Your Approach 您的方法

Think about what you are doing. 想想你在做什么。 You are looping lines from a file and for each line you are creating a database connection and then going all the way to the database to insert the one record. 您正在循环一个文件中的行,并为每一行创建一个数据库连接,然后一直到数据库插入一条记录。 You do this n times where n is the number of records in your text file. 您执行n次,其中n是您的文本文件中的记录数。

The other thing is you are using File.ReadAllLines which will read the entire file into memory: What if the file is really large? 另一件事是您正在使用File.ReadAllLines ,它将把整个文件读入内存:如果文件真的很大怎么办? Can your memory handle it? 你的记忆能应付吗?


A Better Approach 更好的方法

A better approach would be to create one connection, and then go to the database and take a batch of records (50, 100 or more) and do them in one trip. 更好的方法是创建一个连接,然后转到数据库并获取一批记录(50、100或更多),然后一次完成。 Keep doing this until all records are in. 继续执行此操作,直到所有记录都输入为止。

Also, you should use File.ReadLines so it will read each line lazily (it will load the line into memory once it is requested). 另外,您应该使用File.ReadLines以便它会延迟读取每一行(一旦被请求,它将把该行加载到内存中)。

To improve speed, use SqlBulkCopy . 要提高速度,请使用SqlBulkCopy Make sure you read the parts on column mappings. 确保您阅读了有关列映射的部分。

Steps: 脚步:

  1. Read one line from the file. 从文件中读取一行。
  2. Based on this one line create your in-memory table structure. 在这一行的基础上,创建您的内存表结构。

     string[] strArray = line.Split('\\t'); var dt = new DataTable(); for (int index = 0; index < strArray.Length; index++) dt.Columns.Add(new DataColumn()); 
  3. Populate the in-memory datatable from the file: 从文件填充内存数据表:

     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. Send the data to the database: 将数据发送到数据库:

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

You can do step 4 in batches if the file is really large. 如果文件很大,则可以分批执行步骤4。 In the above code the sr variable would be an instance of StreamReader but you can use anyway of reading the file. 在上面的代码中, sr变量将是StreamReader一个实例,但是无论如何您都可以使用它来读取文件。


NOTE: 注意:

This code is not to be copy pasted but used as a guideline so you will need to tweak it to fit your needs. 此代码不可复制粘贴,而只是作为指导,因此您需要对其进行调整以适合您的需求。

You create a transaction for every line inserted, which is pretty much the same as doing everything without a transaction. 您为插入的每行创建一个事务,这与不进行事务的所有操作几乎相同。 You probably should do something like this: 您可能应该执行以下操作:

    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