【问题标题】:C# loops and mass insertC# 循环和批量插入
【发布时间】:2013-06-28 23:31:48
【问题描述】:

以下代码将在我的数据库中插入一些值。它获取 6 个随机值,将这些东西放入一个数组中,然后将其插入到数据库中。

    public void LottoTest(object sender, EventArgs e)
    {
        Dictionary<int, int> numbers = new Dictionary<int, int>();
        Random generator = new Random();
        while (numbers.Count < 6)
        {
            numbers[generator.Next(1, 49)] = 1;
        }

        string[] lotto = numbers.Keys.OrderBy(n => n).Select(s => s.ToString()).ToArray();

        foreach (String _str in lotto)
        {
            Response.Write(_str);
            Response.Write(",");
        }


        var connectionstring = "Server=C;Database=lotto;User Id=lottoadmin;Password=password;";

        using (var con = new SqlConnection(connectionstring))  // Create connection with automatic disposal
        {
            con.Open();
            using (var tran = con.BeginTransaction())  // Open a transaction
            {
                // Create command with parameters  (DO NOT PUT VALUES IN LINE!!!!!)
                string sql =
                    "insert into CustomerSelections(val1,val2,val3,val4,val5,val6) values (@val1,@val2,@val3,@val4,@val5,@val6)";
                var cmd = new SqlCommand(sql, con);
                cmd.Parameters.AddWithValue("val1", lotto[0]);
                cmd.Parameters.AddWithValue("val2", lotto[1]);
                cmd.Parameters.AddWithValue("val3", lotto[2]);
                cmd.Parameters.AddWithValue("val4", lotto[3]);
                cmd.Parameters.AddWithValue("val5", lotto[4]);
                cmd.Parameters.AddWithValue("val6", lotto[5]);


                cmd.Transaction = tran;
                cmd.ExecuteNonQuery(); // Insert Record

                tran.Commit();  // commit transaction
                Response.Write("<br />");
                Response.Write("<br />");
                Response.Write("Ticket has been registered!");
            }
        }


    }

循环并将 MASS 条目插入数据库的最佳方法是什么。比方说,通过 C# 记录 100,000 条记录?我希望能够通过我的方法生成随机数并利用我也有的插入..

【问题讨论】:

  • 使用SqlBulkCopy
  • 不能,因为它的不同价值我的朋友......
  • @PriceCheaperton 当然它是不同的.. 有一个非常快的批量插入但一遍又一遍地只插入相同的值会很奇怪。 SqlBulkCopy 只会读取 SqlDataReader,它不知道值是如何生成的。
  • @SimonBelanger 确实;我最近做了一些元编程工作,将通用枚举器(迭代器块)重新公开为IDataReaders 专门设计(和测试)以定位SqlBulkCopy

标签: c# asp.net loops


【解决方案1】:

对于真正的大规模插入,SqlBulkCopy 是您的朋友。简单但低效的方法就是用数据填充DataTable,然后将其扔到SqlBulkCopy,但它可以通过欺骗@来快两倍(相信我,我已经计时了) 987654325@。为方便起见,我最近将此代码移至 FastMember,因此您可以执行以下操作:

class YourDataType {
    public int val1 {get;set;}
    public string val2 {get;set;}
    ... etc
    public DateTime val6 {get;set;}
}

然后创建一个迭代器块(即一个非缓冲的仅转发阅读器):

public IEnumerable<YourDataType> InventSomeData(int count) {
    for(int i = 0 ; i < count ; i++) {
        var obj = new YourDataType {
           ... initialize your random per row values here...
        }
        yield return obj;
    }
}

然后:

var data = InventSomeData(1000000);
using(var bcp = new SqlBulkCopy(connection))
using(var reader = ObjectReader.Create(data))
{ // note that you can be more selective with the column map
    bcp.DestinationTableName = "CustomerSelections";
    bcp.WriteToServer(reader);
}

【讨论】:

  • +1 - spoofingIDataReader 的速度是原来的两倍,这真是太搞笑了。相同的数据,相同的大小,更高效。伙计,使用DataTable 的算法一定是可怕的!
  • @MichaelPerrenoud 它不是完全“相同的数据” - 不要忘记 DataTable 要求您一次将其全部保存在内存中,并且包括“高级”(在这种情况下我的意思是“不必要的”)功能,例如默认值、约束、索引、更改跟踪、旧/新值、动态列添加等 - 我可以完全理解 DataTable 是如何产生一些开销的。当适当地使用时,DataTable 实际上是相当擅长它的工作。 IMO 的问题在于,它被用于超出它擅长的领域。
  • 很棒的反应马克,我很欣赏你的洞察力,因为现在你提到了所有这些开销,这完全有道理,单独的类的性能不如拥有一些甚至可以优化的 POCO 对象直接从磁盘上读取,而不是将其全部保存在内存中,因为它的实现很简单!再次感谢朋友,我总是从你身上学到一些东西!
  • @Michael 确实,迭代器块非常适合仅从文件等流式传输。显然,如果它只是 CSV,则不会这样做-您只需使用 BCP 命令-线;但对于其他格式(XML、protobuf、JSON 等),c# 只是在批量复制需要时具体化单个对象 - 甜蜜点
【解决方案2】:

您需要 Sql 批量插入。 msdn上有一个不错的教程http://blogs.msdn.com/b/nikhilsi/archive/2008/06/11/bulk-insert-into-sql-from-c-app.aspx

【讨论】:

  • 这取决于您将如何生成数据。我总是生成一个整数数组,然后随机更改索引。在此之后,我使用批量插入将数据加载到数据库
  • @PriceCheaperton - 请参阅 this 示例,该示例批量复制代码中生成的数据。
  • @PriceCheaperton 这并不明显,但我们使用代码中的值的示例 - 值在 DataTable 中。
  • 我打算在页面加载时调用该方法并循环 10 万次大声笑
【解决方案3】:

MSDN Table Value Parameters

基本上,您使用要放入 SqlServer 的数据填充数据表。

DataTable tvp = new DataTable("LottoNumbers");
forach(var numberSet in numbers)
    // add the data to the dataset

然后您使用类似于此的代码通过 ADO 传递数据...

command.Parameters.Add("@CustomerLottoNumbers", SqlDbType.Structured);
command.Parameters["CustomerLottoNumbers"].Value = tvp;

那么你可以使用类似这样的sql...

INSERT CustomerSelections
SELECT * from @CustomerLottoNumbers

【讨论】:

  • 我的 C# 应用会处理唯一的乐透号码...那么这有什么帮助呢??
  • @PriceCheaperton - 你还没有真正解释为什么你必须在代码中生成随机数。
  • 这是用于将其插入数据库的 sql。
  • 我正在开发一个统计应用程序,所以我需要能够使用我的 C# 代码生成数组中的随机值,然后将它们插入数据库。循环需要遍历整个方法...
  • @PriceCheaperton - TSQL 可以生成random 值。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-03
  • 2017-06-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多