Parallel.ForEach在项目列表

时间:2015-09-30 20:52:07

标签: vb.net parallel-processing

我有一长串ID填充的员工列表。我想并行添加数据库以加快处理速度。 vb.net中使用parallel.foreach在列表中的每个项目上调用函数的正确语法是什么。以下是这样做的连续方式。

    Dim employees As New List(Of Employee)()
    For Each element As String In ids
        Dim emp As New Employee(element)
        employees.Add(emp)
    Next

    For Each emp In employees
        emp.AddToDatabase()
    Next

2 个答案:

答案 0 :(得分:4)

语法为:

Parallel.ForEach(employees, Sub(emp) emp.AddToDatabase())

但是,并行执行数据库插入实际上会更快,这是值得怀疑的。唯一可能的加速是在实际插入之前的开销,最后数据库一次只能对表执行一次插入。

您可以尝试加速插入的一件事是在一个查询中放入几个插入,即将员工分成小批量。

答案 1 :(得分:0)

这看起来像XY problem,你已经决定了解决方案。

我建议你最好退一步,找出如何在一个查询中添加所有数据,而不是尽可能快地解决大量查询。通常,一个查询将比许多查询更快。

您在评论中指出“这是一个未来更复杂问题的简单示例”,因此我将举例说明将数据添加到只包含文件名和关键字的列的表中,期望您可以扩展它以供将来使用。

首先,表的定义:

CREATE TABLE [dbo].[Keywords](
    [Filename] [nvarchar](256) NOT NULL,
    [Keyword] [nvarchar](64) NOT NULL
) ON [PRIMARY]

然后是数据库中用户定义的表类型:

CREATE TYPE [dbo].[filename_keyword_tbltype] AS TABLE(
    [Filename] [nvarchar](256) NOT NULL,
    [Keyword] [nvarchar](64) NOT NULL,
    PRIMARY KEY CLUSTERED -- may not apply to you
(
    [Keyword] ASC -- may not apply to you
)WITH (IGNORE_DUP_KEY = OFF) -- may not apply to you
)

必须在用户定义的表类型上设置权限:

GRANT EXECUTE ON TYPE::[filename_tbltype] TO [APPROPRIATE\USER_GOES_HERE]

现在数据库已设置为创建存储过程来处理将发送给它的数据:

CREATE PROCEDURE [dbo].[AddKeywords]
    @Data [dbo].[filename_keyword_tbltype] ReadOnly
AS
BEGIN
    SET NOCOUNT ON;

    INSERT INTO Keywords
    SELECT [Filename],[Keyword]
    FROM @Data;

END

最后可以编写代码以一次性发送所有数据:

Imports System.Data.SqlClient
Imports System.Data.SqlTypes
' ...
sqlcmd = New SqlCommand("AddKeywords", sqlConn)
sqlcmd.CommandType = CommandType.StoredProcedure

Dim tvpData As New List(Of SqlDataRecord)
Dim tvpDataType(1) As SqlMetaData
tvpDataType(0) = New SqlMetaData("Filename", SqlDbType.NVarChar, 256)
tvpDataType(1) = New SqlMetaData("Keyword", SqlDbType.NVarChar, 64)

' metadata.Keywords is a List(Of String) with the keywords for a file
For Each kwd In metadata.Keywords
    Dim rec = New SqlDataRecord(tvpDataType)
    ' smallName is simply the filename
    rec.SetSqlString(0, smallName)
    rec.SetSqlString(1, kwd.ToLower(CultureInfo.InvariantCulture))
    tvpData.Add(rec)
Next

sqlParam = New SqlParameter("@Data", SqlDbType.Structured)
sqlParam.TypeName = "filename_keyword_tbltype"
sqlParam.Value = tvpData

sqlcmd.Parameters.Add(sqlParam)

sqlConn.Open()
sqlcmd.ExecuteNonQuery()
sqlConn.Close()

请注意,所有数据都是一次性发送的,无论是一条记录还是一千条。

参考:Arrays and Lists in SQL Server 2008 - Using Table-Valued Parameters