2013-08-12 33 views
0

我已經編寫了附加從定製c#列表中插入數據到MSAccess的函數。提高OleDB插入到語句中的性能,BeginTransaction CommitTransaction

第僅僅設置了爲每個記錄一個新的連接:

 public static void appenddatatotable(string connectionstring, string tablename, string[] values) 
    { 

      var myconn = new OleDbConnection(connectionstring); 


      var cmd = new OleDbCommand(); 
      cmd.CommandText = "INSERT INTO " + tablename + " ([RunDate],[ReportingGroup], [Tariff], [Year]) VALUES(@RunDate, @ReportingGroup, @Tariff, @Year)"; 

      cmd.Parameters.AddRange(new[] { new OleDbParameter("@RunDate", values[0]), new OleDbParameter("@ReportingGroup", values[1]), new OleDbParameter("@Tariff", values[2]), new OleDbParameter("@Year", values[3])}); 
      cmd.Connection = myconn; 
      myconn.Open(); 
      cmd.ExecuteNonQuery(); 
      myconn.Close(); 

    } 

我後來乾脆在我的值列表循環,並呼籲每個迭代此功能。這工作正常,但速度很慢。

在第二個功能我想包括在功能上環和與BeginTransction和Committransaction工作:

 public static void appenddatatotable2(string connectionstring, string tablename, string datstr, List<PowRes> values) 
    { 

     var myconn = new OleDbConnection(connectionstring); 
     int icounter = 0; 

     var cmd = new OleDbCommand(); 
     OleDbTransaction trans = null; 

     cmd.Connection = myconn; 
     myconn.Open(); 
     foreach (var item in values) 
     { 
      if (icounter == 0) 
      { 
       trans = cmd.Connection.BeginTransaction(); 
       cmd.Transaction = trans; 
      } 

      cmd.CommandText = "INSERT INTO " + tablename + " ([RunDate],[ReportingGroup], [Tariff], [Year]) VALUES(@RunDate, @ReportingGroup, @Tariff, @Year)"; 
      if (string.IsNullOrEmpty(item.yr)) 
       item.yr = ""; 

      cmd.Parameters.AddRange(new[] { new OleDbParameter("@RunDate", datstr), new OleDbParameter("@ReportingGroup", item.RG), new OleDbParameter("@Tariff", item.tar), new OleDbParameter("@Year", item.yr)}); 
      cmd.ExecuteNonQuery(); 
      icounter++; 
      if (icounter >= 500) 
      { 
       trans.Commit(); 
       icounter = 0; 
      } 
     } 
     if (icounter > 0) 
     { 
      trans.Commit(); 
     } 


     myconn.Close(); 

    } 

這也工作正常,但更慢。

我的代碼錯了嗎?我怎麼能加快多個插入?

謝謝!

+0

與問題無關的顯著快,但很重要:你應該在這裏使用'using'語句,對於'myconn'和'cmd',確保即使出現問題也能清除它們。大概也是'trans',但是這是由你的不尋常的用法(分配遲到等)複雜 –

+0

謝謝馬克。好點,我會清理它!關於爲什麼第二個可能會更慢的任何想法? – nik

+0

@npvh,因爲您已經添加了另一個事務開銷。 – Ehsan

回答

1

沒有測試,只是我的猜測你的第二個功能:你在循環添加了太多的參數相同的命令 - cmd.Parameters每次使用之前從來沒有被清除..

正常投入大量的命令集在一個連接中的速度要比在單個連接上一個接一個的速度快得多。

另一種方式來加快你的刀片是所有的INSERT語句轉儲到長文本,用分號隔開,再火一次性提交(我不知道MSACCESS是否支持與否)

編輯:

到更新命令合併爲一個文本:

var updates = values.Select(x => string.Format("INSERT INTO myTable ([RunDate],[ReportingGroup], [Tariff], [Year]) VALUES({0}, {1}, {2}, {3})", 
       datstr, x.RG, x.tar, x.yr)) 
       .Aggregate((m, n) => m + ";" + n); 
cmd.CommandText = update; 

雖然這會對SQL注入的問題。

+0

感謝雷克斯。我不得不承認我認爲這就是我所做的。我如何彙集插入語句然後使用一個提交? – nik

+0

請參閱組合文本命令的編輯部分。但這可能不是一個很好的做法,爲了安全起見,將所有參數設置爲純文本。...... – Rex

+0

感謝您的支持者。但是如果你看看其他的stackoverflow問題,(正如你所說),你可以根據變量名和用戶輸入信息完全搞亂字符串 - 因此我寧願不沿着這條路線走。 – nik

1

這應該是比所有的退出版本

public static void appenddatatotable2(string connectionstring, string tablename, string datstr, List<PowRes> values) 
     { 
      string commandText = "INSERT INTO " + tablename + " ([RunDate],[ReportingGroup], [Tariff], [Year]) VALUES(@RunDate, @ReportingGroup, @Tariff, @Year)"; 
      using (var myconn = new OleDbConnection(connectionstring)) 
      { 
       myconn.Open(); 
       using (var cmd = new OleDbCommand()) 
       { 
        foreach (var item in values) 
        { 
         cmd.CommandText = commandText; 
         cmd.Parameters.Clear(); 
         cmd.Parameters.AddRange(new[] { new OleDbParameter("@RunDate", datstr), new OleDbParameter("@ReportingGroup", item.RG), new OleDbParameter("@Tariff", item.tar), new OleDbParameter("@Year", item.yr) }); 
         cmd.Connection = myconn; 
         cmd.Prepare(); 
         cmd.ExecuteNonQuery(); 
        } 
       } 
      } 
     } 
+1

這可能是值得的只是記錄*爲什麼*這是更快的澄清。 – James

+0

@Ehsan:非常感謝。我發現這是節省的,因爲它使用Marc所建議的使用方法。但它似乎與我的第一個版本沒有什麼不同,因爲它可以單獨連接並執行每個項目。或者我沒有得到它? – nik

+0

實際上它是你的2個版本的組合。這裏連接只打開一次,類似的命令只創建一次。它只會採取訪問 – Ehsan