如何使用 Dapper 批量插入外键?

How to use Dapper for bulk insert with foreign keys?

我有一个像这样的 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 并创建一个发票集合(每个发票都有一定数量的相关销售人员记录)。

我可以想到一个天真的方法来使用 Dapper 执行此操作:遍历每个发票,插入它,获取标识(整数 ID 列),遍历该发票中的每个 SalesPerson,使用我得到的标识插入一个外键。但这似乎会产生很多不必要的流量 to/from 我的 SQL 服务器。

我知道 'bulk' 插入,我可以在其中多次执行插入命令,但我不知道在这种情况下它是如何工作的,因为我不知道外键当时我正在构建参数。

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

Dapper 旨在成为通用 ADO.NET 工具,对特定于提供程序的功能提供一些最低限度的支持。批量插入 不是通用的 API - 这不是通用的批量插入 class。如果您正在使用 SQL 服务器,SqlBulkCopy would be the obvious choice. When combining that with a class-based object-model, 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 而言, 支持 table 值参数,但这需要您创建SQL 服务器中的命名类型。但如果您想考虑这条路线,请参阅 Does Dapper support SQL 2008 Table-Valued Parameters?

table-valued-parameters 选项的一个优点是您可以将 INSERT 语句与 OUTPUT clause 语句结合起来一次性取回所有 ID。相比之下:对于 SqlBulkCopy,您需要在插入 之后查询数据 (本质上:SqlBulkCopy 操作没有任何结果)。