在C#中将数据传递给存储过程EF时的逻辑问题

问题描述 投票:0回答:1

我在SQL Server数据库中有一个包含13个参数的存储过程。在我的C#应用​​程序中,我需要将数据插入到该存储过程中,并且我能够一次插入1个值,但我需要能够插入多个值,如5或10或更多。我有5个数组,将有许多值插入到该存储过程但如果数组的值超过1,则不插入,我认为我的循环没有正确完成。

请看下面的内容。

将为存储过程创建方法的类

using System;
using System.Collections;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using BarcodeReceivingApp.Persistence;
using BarcodeReceivingApp.Persistence.Repositories;

namespace BarcodeReceivingApp.Functionality
{
    public class StoredProcedureInsert
    {
        private readonly BarcodeReceivingFootPrintDbContext _barcodeReceivingFootPrintDbContext = new BarcodeReceivingFootPrintDbContext();

        public void CallManualBlindBarcodeParsingEventRequestFootPrintProcedure(decimal actualPackagedAmount, int actualPackagedPackId, string lotLookupCode,
            int warehouseId, int materialId, string vendorLotLookupCode, DateTime vendorLotManufactureDate, 
            DateTime vendorLotExpirationDate, int shipmentId, decimal netWeight, 
            decimal grossWeight, string serialLookupCode, string licensePlateLookupCode)
        {
            _barcodeReceivingFootPrintDbContext.Database
                .ExecuteSqlCommand("EXEC noram_reporting.ManualBlindBarcodeParsingEventRequest " +
                                   "@ActualPackagedAmount, @ActualPackagedPackId, @LotLookupCode, @WarehouseId, @MaterialId, @VendorLotLookupCode," +
                                   "@VendorLotManufactureDate, @VendorLotExpirationDate, @ShipmentId, @netWeight, @grossWeight, @serialLookupCode, @licensePlateLookupCode",
                    new SqlParameter("@ActualPackagedAmount", actualPackagedAmount),
                    new SqlParameter("@ActualPackagedPackId", actualPackagedPackId),
                    new SqlParameter("@LotLookupCode", lotLookupCode),
                    new SqlParameter("@WarehouseId", warehouseId),
                    new SqlParameter("@MaterialId", materialId),
                    new SqlParameter("@VendorLotLookupCode", vendorLotLookupCode),
                    new SqlParameter("@VendorLotManufactureDate", vendorLotManufactureDate),
                    new SqlParameter("@VendorLotExpirationDate", vendorLotExpirationDate),
                    new SqlParameter("@ShipmentId", shipmentId),
                    new SqlParameter("@netWeight", netWeight),
                    new SqlParameter("@grossWeight", grossWeight),
                    new SqlParameter("@serialLookupCode", serialLookupCode),
                    new SqlParameter("@licensePlateLookupCode", licensePlateLookupCode)
                    );
        }
    }
}

在这里,我调用该方法插入每个参数

private void SendStoredProcedureDataToFootPrint()
{
    var lotList = _connection.ParseLot();
    var netWeightList = _connection.ParseNetWeight();
    var grossWeightList = _connection.ParseGrossWeight();
    var serialNumberList = _connection.ParseSerialNumber();
    var material = _unitOfWork.Shipments.GetLastShipmentMaterialEntry();
    var scanCounts = _connection.CountReceivingBarcodeEntries();
    var packagingId = _unitOfWork.Materials.GetPackagingId();
    var warehouse = _unitOfWork.Warehouses.GetWarehouseIdQuery();
    var shipment = _unitOfWork.Shipments.GetLastShipmentIdEntry();
    var licensePlate = _unitOfWork.LicensePlates.GetLastCreatedLicensePlate();

    try
    {
        for (var i = 0; i < _connection.GetBarcodeList().Count ; i++)
        {

            _storedProcedureInsert.CallManualBlindBarcodeParsingEventRequestFootPrintProcedure(scanCounts, packagingId, lotList[i], warehouseId: warehouse, materialId: 5785,
                vendorLotLookupCode: lotList[i], vendorLotManufactureDate: DateTime.Now,
                vendorLotExpirationDate: DateTime.Now, shipmentId: shipment,
                netWeight: Convert.ToDecimal(netWeightList[i]) / 100,
                grossWeight: Convert.ToDecimal(grossWeightList[i]) / 100,
                serialLookupCode: serialNumberList[i], licensePlateLookupCode: licensePlate);
        }
    }
    catch (Exception exception)
    {
        MetroMessageBox.Show(null, exception.Message, "Error Message", MessageBoxButtons.OK, MessageBoxIcon.Warning);
        throw;
    }
}

所以,就像我说的那样,如果我为每个参数插入1个数据,但如果批量列表,netweightlist,grossweightlist和serialnumberlist数组有多个数据,它将不会发送到存储过程。

因此,目标是插入数据并不重要我需要插入许多记录,一次可以是一个或多个。

在stackoverflow或google等其他问题上无法找到一个好的解决方案。

sql-server entity-framework c#-4.0 ef-migrations
1个回答
1
投票

请使用表值参数来处理这些场景。但是您必须将数据转换为DataTable。对于每个阵列,都会有相应的数据表。

我想给你一个主意。

  1. 将每个C#列表转换为DataTable。 将每个数组(例如,serialNumberList转换为DataTable。)(如果它只是原始数据,那么只有一列对应,如果它的对象则完成行。在这种情况下每行:每个单元将对应于对应于C#对象数据成员的数据。)
  2. 在SQL Server中创建“可编程性”下的数据类型,它将从您的C#代码接收这些数据表。此数据类型与C#结构中具有相同SQL个别类型的数据完全相同。
  3. 无论你在循环中做什么(关于转换或做一些数学,在进入SQL之前都在相同的列表中执行。最后,在已经处理数据时将数据传递给SQL)。
  4. 在将数据传递给SQL之前,您应该知道数据必须作为表值参数传递。所以它的数据类型必须选择为SQLDataType.Structured。
  5. 对于每个非列表数据项,不要创建任何DataTable。通过使用.NET中的SQL本机数据类型,直接传递它。

如果您以这种方式解决问题,请告诉我。我相信,它会成功。此外,如果您还想知道如何传递复杂结构/简单本机数据类型数组或对象数组,请参阅以下链接。

T-SQL - Insert Data into Parent and Child Tables

© www.soinside.com 2019 - 2024. All rights reserved.