2013-08-12 28 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