C# 使用存储过程将多行插入到两个表中的Dapper
我正在asp.net核心MyWebAPI项目中使用Dapper。我需要创建主记录并将一组行插入到子表中C# 使用存储过程将多行插入到两个表中的Dapper,c#,.net,dapper,asp.net-core-webapi,C#,.net,Dapper,Asp.net Core Webapi,我正在asp.net核心MyWebAPI项目中使用Dapper。我需要创建主记录并将一组行插入到子表中 Ex. OrdersMaster table create an order id in this table OrderDetails table ordermasterid order items 我怎样才能用整洁的方式做到这一点?如果可能的话,请共享一些代码片段。我将把插入操作实现为事务存储过程,然后从.NET应用程序调用它 您可能需要表值类型来传递数
Ex. OrdersMaster table
create an order id in this table
OrderDetails table
ordermasterid
order items
我怎样才能用整洁的方式做到这一点?如果可能的话,请共享一些代码片段。我将把插入操作实现为事务存储过程,然后从.NET应用程序调用它 您可能需要表值类型来传递数据列表,如下所示:
CREATE TYPE List_Of_Items AS TABLE (
ItemID INT NOT NULL,
Quantity INT NOT NULL
)
程序可能是这样的
CREATE PROC Insert_Order_With_Details (
@CustomerId INT,
@Items List_Of_Items
) AS
BEGIN
BEGIN TRANSACTION
INSERT INTO OrdersMaster (CustomerId) VALUES @CustomerId
DECLARE @OrderID INT
SET @OrderID = SCOPE_IDENTITY() --last assigned id
INSERT INTO OrderDetails (OrderId, CustomerId, ItemId, Quantity)
SELECT @OrderID, @CustomerID, ItemID, Quantity
FROM @Items
COMMIT
END
然后在C中,我建议创建创建TVP的方法。这并不像你想的那么简单。这需要使用Microsoft.SqlServer.Server和Dapper.Tvp
commandType参数非常重要。它默认为纯SQL文本,如果发送进程名称,则会出错
如果您想同时下多个订单,则需要使用表值参数和Dapper.Tvp包
请参阅此问题以及来自Microsoft的TVP文档。我不认为所有SQL供应商都支持TVP。使用存储过程(如其他答案中所述)是一个很好的解决方案。我的答案在没有存储过程的情况下实现了相同的功能 您必须使用事务处理。这样,所有更改都将提交或回滚。下面的代码假定您正在使用标识作为主键。有关我在下面代码中使用的@标识的讨论,请参考问题 虽然代码不完整,但我已经给出了详细的注释来解释这些步骤
using (var connection = new SqlCeConnection("connection_string"))
{
connection.Open();
//Begin the transaction
using (var transaction = connection.BeginTransaction())
{
//Create and fill-up master table data
var paramMaster = new DynamicParameters();
paramMaster.Add("@XXX", ...);
....
//Insert record in master table. Pass transaction parameter to Dapper.
var affectedRows = connection.Execute("insert into OrdersMaster....", paramMaster, transaction: transaction);
//Get the Id newly created for master table record.
//If this is not an Identity, use different method here
newId = Convert.ToInt64(connection.ExecuteScalar<object>("SELECT @@IDENTITY", null, transaction: transaction));
//Create and fill-up detail table data
//Use suitable loop as you want to insert multiple records.
//for(......)
foreach(OrderItem item in orderItems)
{
var paramDetails = new DynamicParameters();
paramDetails.Add("@OrderMasterId", newId);
paramDetails.Add("@YYY", ...);
....
//Insert record in detail table. Pass transaction parameter to Dapper.
var affectedRows = connection.Execute("insert into OrderDetails....", paramDetails, transaction: transaction);
}
//Commit transaction
transaction.Commit();
}
}
您可能应该定义一个存储过程来在事务内部完成这项工作,然后从.NET应用程序调用该过程。您有权添加存储过程吗?是的,我可以创建存储过程,但需要在表中输入IEnumerable。我想用dapper来做这件事。在详细信息表中,每行需要什么样的数据?这可能在您的过程中用作TVP,只需向OrderMaster插入一个,然后您就可以获得具有SCOPE_标识的订单ID,并将其用于OrderDetails中的行;Error=>对类型“SqlDataRecord”的引用声称该类型是在“System.Data”中定义的,但找不到该类型。此问题可能对Core有所帮助
using (var cn = new SqlConnection(myConnectionString))
{
var p = new DynampicParametersTvp(new {
CustomerId = myCustomerId
});
p.AddItemsTable(items);
cn.Execute("Insert_Order_With_Details", p, commandType: CommandType.StoredProcedure);
}
using (var connection = new SqlCeConnection("connection_string"))
{
connection.Open();
//Begin the transaction
using (var transaction = connection.BeginTransaction())
{
//Create and fill-up master table data
var paramMaster = new DynamicParameters();
paramMaster.Add("@XXX", ...);
....
//Insert record in master table. Pass transaction parameter to Dapper.
var affectedRows = connection.Execute("insert into OrdersMaster....", paramMaster, transaction: transaction);
//Get the Id newly created for master table record.
//If this is not an Identity, use different method here
newId = Convert.ToInt64(connection.ExecuteScalar<object>("SELECT @@IDENTITY", null, transaction: transaction));
//Create and fill-up detail table data
//Use suitable loop as you want to insert multiple records.
//for(......)
foreach(OrderItem item in orderItems)
{
var paramDetails = new DynamicParameters();
paramDetails.Add("@OrderMasterId", newId);
paramDetails.Add("@YYY", ...);
....
//Insert record in detail table. Pass transaction parameter to Dapper.
var affectedRows = connection.Execute("insert into OrderDetails....", paramDetails, transaction: transaction);
}
//Commit transaction
transaction.Commit();
}
}