如果您有多行数据,在对存储过程的一次调用中一次性插入所有行会更有效。为此,您将数据序列化为 xml,然后调用将 xml 作为字符串参数的存储过程。
AFAIK 你不能序列化一个字典,但是你可以序列化一个列表。
所以我建议您遍历您的字典(字典列表),用适当的值填充一个列表。我倾向于为此使用结构,但简单的类也可以正常工作,例如:
Public Class DBData
Public pKey As Integer
Public pValue As Double
Public Sub New(key As Integer, val As Double)
pKey = key
pValue = val
End Sub
Public Sub New()
pKey = 0
pValue = 0.0
End Sub
End Class
创建您的列表并填写它,例如:
Dim myList As New List(Of DBData)
For Each kvPair In dict
myList.Add(New DBData(kvPair.Key, kvPair.Value))
Next
现在来序列化一点魔法:
Dim sw As New StringWriter
Dim serializer As New XmlSerializer(GetType(List(Of DBData)))
Dim ns As New XmlSerializerNamespaces()
serializer.Serialize(sw, myList)
Dim xml As String
xml = sw.ToString
Dim pos As Integer
pos = xml.IndexOf("<Array")
xml = xml.Substring(pos)
注意这里我剥离了刚刚创建的 xml 的标题。那是因为如果包含标头,我永远无法让 SQL Server 工作 - 你可能可以,我只是看起来不够努力。
我们这样调用存储过程(显然将连接字符串更改为适合您的字符串):
Using conn As New SqlConnection("Integrated Security=true; Initial Catalog=dbname; Data Source=servername")
Using cmd As New SqlCommand("uspDBDataInsert", conn)
cmd.CommandType = CommandType.StoredProcedure
Dim param As SqlParameter
param = cmd.CreateParameter
param.ParameterName = "@dbdata"
param.DbType = DbType.String
param.Value = xml
cmd.Parameters.Add(param)
conn.Open()
cmd.ExecuteNonQuery()
conn.Close()
End Using
End Using
对于 SQL Server,所需的过程如下所示:
CREATE PROCEDURE [dbo].[uspDBDataInsert]
-- Add the parameters for the stored procedure here
@dbdata varchar(MAX)
AS
BEGIN try
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
declare @idoc int
--Create an internal representation of the XML document
EXEC sp_xml_preparedocument @idoc OUTPUT, @dbdata
insert into DBData
(
id, rowvalue
)
select
pKey,pValue
FROM OPENXML (@idoc, '/ArrayOfDBData/DBData',2)
WITH (
pKey int,
pValue float
)
select @@ROWCOUNT
end try
begin catch
declare @msg nvarchar(200)
SELECT @msg = ('Error during insert of DBData...')
end catch
显然,您需要将 ArrayOf 更改为您的班级名称,当然还要使用您自己的表格。
虽然我在这里只展示了一个简单的键/值对,但您可以以完全相同的方式填充多列表。
需要注意的一点:你的类/结构必须在公共模块中是公共的,否则序列化将不起作用。此外,如果你为一个类提供你自己的参数构造函数(就像我一样),你还必须提供一个无参数的构造函数,否则序列化器将再次反对。
HTH
附录
我忘了说,为了让 VB 工作你需要:
Imports System.IO
Imports System.Xml.Serialization
Imports System.Data.SqlClient