【问题标题】:Best way to insert large amounts of data from a WCF call into SQL将 WCF 调用中的大量数据插入 SQL 的最佳方法
【发布时间】:2011-10-13 18:51:38
【问题描述】:

我正在调用返回大量 XML(1000 行)的第三方 Web 服务。将 XML 放入底层 SQL Server 2008 R2 表的最佳方法是什么。目前我正在检索 XML 并使用关联的 XSD 反序列化为 .NET 类集合。然后我遍历集合,多次调用 INSERT 存储过程。性能还不错,但我确信必须有更快的方法来做到这一点。我应该查看 SqlBulkCopy 吗?我听说 LINQ-TO-SQL 在批量插入/更新方面很慢。任何的建议都受欢迎。

【问题讨论】:

    标签: .net wcf sql-server-2008


    【解决方案1】:

    阅读SQLXMLBulkLoad4,它似乎可以处理将 XML 批量插入到 sql server 中。我自己没试过,但值得一试。

    如果这不起作用,请查看System.Data.SqlClient.SqlBulkCopy 使用 SqlBulkCopy,我在大约 4 秒内从一个文件中读取了 200.000 行数据。

    以下代码将文件名作为参数,读取所有行并将这些行转换为添加到数据表的数据行(数据表必须与目标表具有相同的格式,在这种情况下我使用强类型数据表)。当数据表包含 1000 行时,我使用 WriteToServer 方法将其写入服务器。然后清空数据表并重新开始。

    你可以很容易地改变它来转换你的 xml 文档中的行。

    Imports System.IO
    Imports System.Data.SqlClient
    
        Public Sub ParseFile(ByVal filename As String)
        Using BulkCopy As SqlBulkCopy = New SqlBulkCopy(My.Settings.DBConnectionString, SqlBulkCopyOptions.TableLock)
            BulkCopy.DestinationTableName = "Destinationtable"
            Dim TableDataSet As New MyDS.UserDataTable
            Try
                Using sr As StreamReader = System.IO.File.OpenText(filename)
                    Dim l As String = Nothing
                    l = sr.ReadLine()
                    If Not l Is Nothing Then AddToDS(l, TableDataSet)
                    Do Until l Is Nothing
                        l = sr.ReadLine()
                        If Not l Is Nothing Then AddToDS(l, TableDataSet)
                        If TableDataSet.Rows.Count > My.Settings.BulkSize Then 'bulk copy every 1000 rows to db.
                            BulkCopy.WriteToServer(TableDataSet)
                            TableDataSet.Rows.Clear()
                        End If
                    Loop
                    If TableDataSet.Rows.Count > 0 Then 'write the rest
                        BulkCopy.WriteToServer(TableDataSet)
                        TableDataSet.Rows.Clear()
                    End If
                    sr.Close()
                End Using
            Catch ex As Exception
                MsgBox("Error:" & ex.Message)
            End Try
        End Using
    End Sub
    
    Sub AddToDS(ByVal s As String, ByRef ds As MyDS.UserDataTable)
        'row should contain username + tab + carname
        Dim arr() As String = s.Split(vbTab)
        If arr.Count < 2 Then Exit Sub
        ds.AddUserRow(arr(0).Trim, arr(1).Trim)
    End Sub
    

    【讨论】:

    • 感谢 Stefan。我见过很多这样的代码示例。这是事务性的,即如果一个插入失败,所有前一行插入都会回滚吗?如果不是,您如何使其具有事务性?
    • SqlBulkCopy 是 IDisposable - 您应该将其包装在 Using 语句中,就像您为 StreamReader 所做的那样。
    • SqlBulkCopy 是全有或全无的事情。它不会导入某些记录,而不会导入其他记录。
    • Graymatter,是的,重要的是阅读主题并在使用之前准确理解 SqlBulkCopy 的作用。我建议在将其投入生产之前在 msdn 链接上花一个小时并进行一些谷歌搜索。 ;)
    • Myles J,我推荐阅读这篇文章,4guysfromrolla.com/articles/111109-1.aspx
    猜你喜欢
    • 1970-01-01
    • 2012-08-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-16
    • 1970-01-01
    • 2018-04-24
    • 1970-01-01
    相关资源
    最近更新 更多