如何使用Dapper进行带外键的批量插入?

时间:2016-02-19 02:47:54

标签: c# sql-server bulkinsert dapper

我有一个像这样的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服务器的大量不必要的流量。

我知道&#39;批量&#39;插入我可以多次执行插入命令的地方,但我不知道在这种情况下它是如何工作的,因为我在构建参数时不知道外键。

有没有比我上面概述的天真方式更好的方法来执行此插入? Dapper是错误的工具吗? (我使用SQL Server;如果有一些tSQL命令可以帮助我,我不知道它们)

1 个答案:

答案 0 :(得分:3)

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);
}

dapper 而言, 支持表值参数,但这需要您在SQL Server中创建命名类型。但是,如果您想考虑该路线,请参阅Does Dapper support SQL 2008 Table-Valued Parameters?

table-valued-parameters选项的一个优点是,您可以将INSERT语句与OUTPUT clause结合使用,以便一次性恢复所有ID。相比之下:使用SqlBulkCopy,您需要在插入之后查询数据(实际上:没有任何内容从SqlBulkCopy操作返回)。