Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/312.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用存储过程将多行插入到两个表中的Dapper_C#_.net_Dapper_Asp.net Core Webapi - Fatal编程技术网

C# 使用存储过程将多行插入到两个表中的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应用程序调用它 您可能需要表值类型来传递数

我正在asp.net核心MyWebAPI项目中使用Dapper。我需要创建主记录并将一组行插入到子表中

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