0

我已经编写了将自定义 c# 列表中的数据插入 MSAccess 的附加函数。

第一个简单地为每个单独的记录集设置一个新连接:

        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();

    }

这也可以正常工作,但速度更慢。

我的代码错了吗?我怎样才能加快多次插入?

谢谢!

4

2 回答 2

1

没有测试,只是我对您的第二个功能的猜测:您在循环中向同一命令添加了太多参数 - cmd.Parameters 在每次使用之前从未被清除..

通常在一个连接中提交大量命令比在单个连接中一个一个地执行要快得多。

另一种加快插入速度的方法是将所有插入语句转储为长文本,用分号分隔,然后一次性触发提交(我不确定 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 注入问题。

于 2013-08-12T09:24:20.417 回答
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();
                    }
                }   
            }
        }
于 2013-08-12T09:33:14.613 回答