我正在编写一个将数据写入SQL Server 2008r2的.NET应用程序。我有两个插入数据的选项,要么我可以创建一个大的字符串插入语句,并将其作为文本命令发送,或者我可以在.NET DataTable中收集数据,并将其作为表值参数传递。每种方法的好处和成本是什么?
(我省略了很多代码,因为我只是询问相关的好处,而不是具体的语法)
e.g:
选项1:
string insert = @"insert into MyTable (id, val) values
( 1, 'a'),(2,'b'),(3,'c'),(4,'d');"
选项2:
DataTable dt = new DataTable();
dt.Columns.Add("id", typeof(int));
dt.Columns.Add("val", typeof(string));
....
create procedure uspMyProc
@tt ttMyTableType readonly
as
begin
insert into TestTable1 (id, strValue)
select myId, myVal from @tt;
end"
感谢您的帮助。
答案 0 :(得分:7)
选项3:在第一个实例中,我将使用一个insert语句的参数填充插入存储过程,并在C#代码的循环中多次调用它:
选项4 :如果您确实要插入 批次 行,或许您需要查看SqlBulkCopy class。它会消耗DataTable
,DataRow
或IDataReader
。你可以使用一些自定义代码从对象列表中创建IDataReader
,这里有一个问题:
Get an IDataReader from a typed List
我认为这取决于。
如果您真的想以表格形式传递多行参数,无论出于何种原因,请使用表值参数 - 这就是它的用途。
我见过选项1 - 一些通用的DAL代码会编写SQL“批处理”命令来运行。它起作用,但没有对注射攻击提供任何防御。参数化SQL可以。
所有这一切,我倾向于从代码中插入每行一次调用插入sproc - 调用将完全参数化并且性能良好。如果性能成为问题,我会赞成选项4。
答案 1 :(得分:5)
有多大?如果它是巨大的,没有什么比SqlBulkCopy更好。我实际上发现TVP表现令人失望。对于查询计划的重用,我是参数化和大量重用语句的粉丝。 Dapper可以帮助您,允许您将对象列表传递给查询 - 然后它将按成员名称添加每个对象的命名参数,每秒数千次操作。例如:
conn.Execute(
"insert foo (Id,Name) values (@Id,@Name)",
listOfObjects);
这将迭代列表并依次使用每个对象的.Id
和.Name
来执行查询。
答案 2 :(得分:4)
值限制为1000
值似乎存在一些性能问题
Insert Performance Issues With Multiple Values
我使用TVP插入数千行,这对我很有用。我使用List集合作为TVP源,因为DataTable有更多的开销。如果可以的话,插入按PK排序的行。
据说我会尝试Marc Gravell的答案。
JNK普遍不信任TVP。