我有一个C#数据结构,如下所示:
public class Invoice
{
public string InvoiceNumber {get;set;}
public List<SalesPerson> SalesPersons {get;set;}
}
public class SalesPerson
{
public string Name {get;set;}
}
这对应于两个表:Invoice和SalesPerson。发票可以包含任意数量的这些关联。
现在,我正在创建一个批量上传工具,接受CSV并创建一个发票集合(每个发票都有一些相关的SalesPerson记录)。
我可以想到用Dapper做一个天真的方法:遍历每个Invoice,插入它,获取identity(一个整数ID列),遍历该发票中的每个SalesPerson,使用我获得的身份作为外键插入。但这似乎是我的SQL服务器的大量不必要的流量。
我知道'批量'插入,我可以多次执行插入命令,但我不知道在这种情况下它会如何工作,因为我在构建时不知道外键参数。
有没有比我上面概述的天真方式更好的方法来执行此插入? Dapper是错误的工具吗? (我正在使用SQL Server;如果有一些tSQL命令可以帮助我,我不知道它们)
Dapper旨在成为一个通用的ADO.NET工具,对提供程序特定的功能提供一些最小的支持。批量插入不是通用API - 不是通用批量插入类。如果您使用的是SQL Server, SqlBulkCopy
将是显而易见的选择。将其与基于类的对象模型相结合时, FastMember是一个很好的盟友。例如:
var data = ... // some List<Foo> where Foo has Id, Name and Description
using(var bcp = new SqlBulkCopy(connection)) // SqlBulkCopy
using(var reader = ObjectReader.Create(data, "Id", "Name", "Description")) // FastMember
{
// these bits are part of the SqlBulkCopy API; WriteToServer accepts *either* a
// DataTable or an IDataReader; we're providing the latter via FastMember
bcp.DestinationTableName = "SomeTable";
bcp.WriteToServer(reader);
}
在短小精悍的方面, 有表值参数的支持,但是这需要你在SQLServer,创建一个名为类型。但是,如果您想考虑该路由,请参阅Dapper是否支持SQL 2008表值参数?
table-valued-parameters选项的一个优点是,您可以将INSERT
语句与OUTPUT
子句组合在一起以获取所有ID。相比之下:使用SqlBulkCopy
您需要在插入后查询数据(实际上:没有任何内容从SqlBulkCopy
操作返回)。