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

本文关键字:插入 何使用 Dapper 行带 | 更新日期: 2023-09-27 18:35:28

我有一个C#数据结构,如下所示:

public class Invoice
{
    public string InvoiceNumber {get;set;}
    public List<SalesPerson> SalesPersons {get;set;}
}
public class SalesPerson
{
    public string Name {get;set;}
}

这对应于两个表:发票和销售人员。发票可以具有任意数量的这些关联。

现在,我正在创建一个批量上传工具,采用 CSV 并创建发票集合(每个发票都有一定数量的关联销售人员记录)。

我可以想到一种天真的方法来使用 Dapper 执行此操作:遍历每张发票,插入它,获取标识(整数 ID 列),遍历该发票中的每个销售人员,使用我获得的身份作为外键插入。但这似乎会有很多不必要的流量进出我的SQL服务器。

我知道"批量"插入,我可以多次执行插入命令,但我看不出在这种情况下如何工作,因为我在构造参数时不知道外键。

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

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

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 中创建命名类型。但是,如果要考虑该路由,请参阅 Dapper 是否支持 SQL 2008 表值参数?

表值参数选项的一个优点是,您可以将 INSERT 语句与 OUTPUT 子句组合在一起,一次性恢复所有 id。相比之下:使用SqlBulkCopy,您需要在插入查询数据(本质上:SqlBulkCopy操作不会返回任何内容)。