【问题标题】:How to UPDATE thousands of records in an MDB file in C#如何在 C# 中更新 MDB 文件中的数千条记录
【发布时间】:2014-02-18 16:17:35
【问题描述】:

我最近向question 询问了如何在 C# 中的 MDB 文件中插入 100,000 条记录。给出的答案将所需时间从 45 秒减少到 10 秒。使用数字表甚至可以将时间缩短到 2~3 秒。

现在我在更新类似的数据库时遇到问题。在这种情况下,我不想实际更新 100,000 条记录,而是从已经创建的 MDB 文件中更新大约 10,000 条记录,其中包含 100,100 条记录。

这是我的代码:

Stopwatch sw = new Stopwatch();
sw.Start();
OleDbConnection con = new OleDbConnection();
string dbProvider = "PROVIDER=Microsoft.Jet.OLEDB.4.0;";
string dbSource = "Data Source = D:/programming/sample.mdb";
con.ConnectionString = dbProvider + dbSource;
con.Open();
string query = "SELECT * FROM tblBooks";

DataSet ds = new DataSet();
OleDbDataAdapter da = new OleDbDataAdapter(query, con);
da.Fill(ds,"Books Table");
for (int i = 0; i < 10000; i++)
{
    ds.Tables[0].Rows[i][1] = "Book" + i.ToString();    
}


OleDbCommandBuilder cb = new OleDbCommandBuilder(da);
da.UpdateCommand = cb.GetUpdateCommand();
da.Update(ds, "Books Table");

con.Close();
sw.Stop();
Console.WriteLine(String.Format("{0:0.0} seconds", sw.ElapsedMilliseconds / 1000.0));

更新 10000 条记录(仅一个字段)大约需要 24 秒!

我还有另一个执行良好的代码:

Stopwatch sw = new Stopwatch();
sw.Start();
OleDbConnection con = new OleDbConnection();
string dbProvider = "PROVIDER=Microsoft.Jet.OLEDB.4.0;";
string dbSource = "Data Source = D:/programming/sample.mdb";
con.ConnectionString = dbProvider + dbSource;
OleDbCommand cmd = new OleDbCommand();
cmd.Connection = con;
con.Open();
cmd.CommandText = "UPDATE tblBooks SET [Title] = @title";
cmd.Parameters.AddWithValue("@title", "Book");
cmd.ExecuteNonQuery();
con.Close();
sw.Stop();
Console.WriteLine(String.Format("{0:0.0} seconds", sw.ElapsedMilliseconds / 1000.0));

我发现当我使用上面的代码时,我能够在不到一秒(0.4 秒)的时间内更新整个表(100,000 条记录)。但是在这个版本中,我不知道如何选择性地只更新表的一部分以及如何为每条记录分配不同的值(书 1、书 2...)。我的意思是我希望能够更新例如表中的记录 4000 到 14000 并将书 1、书 2 和...分配给标题字段。

【问题讨论】:

  • 你考虑过使用 Transactions 吗?请参阅其他问题以获取有关如何使用它的一些示例:stackoverflow.com/questions/18183297/…
  • @Remou 绝对不是,我只是没看懂前面例子中的数字表。你能帮助我正确的方向吗?
  • 我不认为你走错了路。我了解您不想在每次操作时更新整个表。您意识到单个 SQL 查询比启动负载的数据适配器快得多。因此,您希望通过使用尽可能少的 SQL 语句来进行选择,这是正确的路径。我建议你看一些关于“WHERE”SQL 语句的提示:这就是你所需要的。
  • 并非所有应用程序都以这种方式工作。有时,数据持久性被推迟到一个专用线程或服务,它在后台将数据保存到数据库、文件......但是在用户工作时支持对数据库的更改是很常见的。
  • 不客气。 Gord Thompson 的回答肯定会为您指明方向。

标签: c# ms-access oledb


【解决方案1】:

只是为了给您另一个选项来考虑(正如 4dmonster 在对您之前的问题的评论中所建议的那样),这里是更新 Access 数据库的 DAO Recordset 方式。它“跳过”前 4,000 条记录,并将接下来的 10,000 条记录更新为“Book 1”、“Book 2”、...。

在许多情况下,DAO 仍然是对 Access 数据库执行逐行更新的最快方法。在我的机器上执行以下代码需要 2.5 秒。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DAO;

namespace daoConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            var sw = new System.Diagnostics.Stopwatch();
            sw.Start();

            // This code requires the following COM reference in your project:
            //     Microsoft DAO 3.6 Object Library
            //
            var dbe = new DBEngine();
            Database db = dbe.OpenDatabase(@"C:\Users\Gord\Desktop\speed.mdb");
            Recordset rst = db.OpenRecordset(
                    "SELECT TOP 4001 ID FROM tblBooks ORDER BY ID",
                    RecordsetTypeEnum.dbOpenSnapshot);
            rst.MoveLast();
            int startID = rst.Fields["ID"].Value;
            rst.Close();
            rst = db.OpenRecordset(
                    String.Format(
                        "SELECT TOP 10000 Title FROM tblBooks WHERE ID >= {0} ORDER BY ID", 
                        startID),
                    RecordsetTypeEnum.dbOpenDynaset);
            int i = 1;
            while (!rst.EOF)
            {
                rst.Edit();
                rst.Fields["Title"].Value = String.Format("Book {0}", i++);
                rst.Update();
                rst.MoveNext();
            }
            rst.Close();

            sw.Stop();
            Console.WriteLine(String.Format("{0:0.0} seconds", sw.ElapsedMilliseconds / 1000.0));
        }
    }
}

【讨论】:

  • 谢谢你,Gord,你今天真的救了我,我从你身上学到了很多。再问一个问题,如果我使用 SQL Server Express,速度会有什么不同吗?
  • @Vahid 像许多类似的问题一样,答案是“视情况而定”。对于逐行更新,使用 SQL Server 可能不会明显更快。但是,T-SQL(SQL Server 使用的 SQL 方言)将为您提供更多选项来避免逐行操作,例如使用递归 CTE(通用表表达式)生成数字表“即时”。当然,在处理速度很重要的大量行时,我个人更喜欢使用 SQL Server。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-21
  • 2012-01-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多