Не удалось сохранить несколько заказов в базе данных SQL сервера, когда несколько пользователей размещают заказ через ASP. NET API 2 одновременно - PullRequest
0 голосов
/ 09 мая 2020

У меня есть веб-приложение, которое работает в IIS 7 и использует SQL Server 2014 и веб-API2 по принципу SOLID.

У меня есть таблица заказов, которая содержит 51 столбец, в котором я сохраняю детали заказов от нескольких клиентов.

Сначала я проверяю детали заказа (дубликат, наличие идентификатора заказа и т.д. c), а затем сохраняю его в той же таблице.

Мой MVC контроллер украшен с асинхронным типом.

Я использую транзакцию и ведение журнала в хранимой процедуре, где я написал запрос Insert.

Я искал ту же проблему в Google, но немного запутался, кто должен реализовать быстрое решение для этого.

Мои вопросы:

  1. Какой должна быть правильная конструкция системы для обработки такого одновременного запроса заказа.

  2. Как мне разработать таблицы базы данных или хранимую процедуру, чтобы порядок мог быть успешно сохранен.

  3. Как мне оптимизировать или представить новые метод кодирования для решения такого параллельного трафика c как минимум 500 заказов c.

Я был бы очень рад, если бы кто-нибудь мог помочь мне с примером.

Error occurred on 10/5/2020 10:43:12.968, at bookingController/CacheOrderDetails Action
System.InvalidOperationException: BeginExecuteReader requires an open and available
Connection. The connection's current state is connecting.
   at System.Data.SqlClient.SqlCommand.<>c.<ExecuteDbDataReaderAsync>b__174_0(Task`1 result)
   at System.Threading.Tasks.ContinuationResultTaskFromResultTask`2.InnerInvoke()
   at System.Threading.Tasks.Task.Execute()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
   at Dapper.SqlMapper.<QueryAsync>d__23`1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at DAL.DbHelper.<StoredProcWithParamsAsync>d__20`1.MoveNext() in D:\SamWorkspace\DMS_Live_28\DAL\DbHelper.cs:line 303
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Repository.Impl.ApiIntegration.<CacheOrderDetails>d__1.MoveNext() in D:\SamWorkspace\DMS_Live_28\Repository\Impl\ApiIntegration.cs:line 25
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
   at bookingController.<CacheOrderDetails>d__59.MoveNext() in c:\DMS\LIVE_CODE\DmsLive_PublishCode\App_Code\api\bookingController.cs:line 1357

ActionMethod

 public async Task<string> CacheOrderDetails(modelManifest Obj, Int64 UserId, Int64 CustId)
{
    try
    {
        StringBuilder message = new StringBuilder("");
        #region declare payload for Save Manifest
        var data = new
        {
            CreatedById = UserId,
            CustId = CustId,
            AwbNo = Obj.AWB_NUMBER,
            OrderNo = Obj.ORDER_NUMBER,
            ProductType = Obj.PRODUCT,
            Consignee = Obj.CONSIGNEE,
            ConsigneeAdd1 = Obj.CONSIGNEE_ADDRESS1,
            ConsigneeAdd2 = Obj.CONSIGNEE_ADDRESS2,
            ConsigneeAdd3 = Obj.CONSIGNEE_ADDRESS3,
            DestCity = Obj.DESTINATION_CITY,
            DestPin = Obj.PINCODE,
            State = Obj.STATE,
            Mobile = Obj.MOBILE,
            Telephone = Obj.TELEPHONE,
            ItemDesc = Obj.ITEM_DESCRIPTION,
            Pieces = Obj.PIECES,
            Colvalue = Obj.COLLECTABLE_VALUE,
            DeclValue = Obj.DECLARED_VALUE,
            ActualWeight = Obj.ACTUAL_WEIGHT,
            VolmWeight = Obj.VOLUMETRIC_WEIGHT,
            Length = Obj.LENGTH,
            Breadth = Obj.BREADTH,
            height = Obj.HEIGHT,
            PickupName = Obj.PICKUP_NAME,
            PickupAdd1 = Obj.PICKUP_ADDRESS_LINE1,
            PickupAdd2 = Obj.PICKUP_ADDRESS_LINE2,
            PickupPin = Obj.PICKUP_PINCODE,
            PickupPhone = Obj.PICKUP_PHONE,
            PickupMobile = Obj.PICKUP_MOBILE,
            ReturnPin = Obj.RETURN_PINCODE,
            ReturnName = Obj.RETURN_NAME,
            ReturnAdd1 = Obj.RETURN_ADDRESS_LINE1,
            ReturnAdd2 = Obj.RETURN_ADDRESS_LINE2,
            ReturnPhone = Obj.RETURN_PHONE,
            ReturnMobile = Obj.RETURN_MOBILE,
            VendorCode = Obj.VENDOR_CODE,
        };
        #endregion
        if (data != null)
        {
            //  Int32? ShipmentId = client.CreateShipment_ApiOnly(data);
            Int32? ShipmentId = await client.CacheOrderDetails(data);
            if (ShipmentId > 0 & Obj.PRODUCT.Contains("REV"))
            {
                #region declare payload for Save Manifest (QC params)
                var QcParam = new
                {
                    // ShipmentId = ShipmentId,
                    TempId = ShipmentId,
                    DrsUid = 0,
                    QC1_Text = Obj.QC1_Text,
                    QC2_Text = Obj.QC2_Text,
                    QC3_Text = Obj.QC3_Text,
                    QC4_Text = Obj.QC4_Text,
                    QC5_Text = Obj.QC5_Text,
                    QC6_Text = Obj.QC6_Text,
                    QC7_Text = Obj.QC7_Text,
                    QC8_Text = Obj.QC8_Text,
                    QC9_Text = Obj.QC9_Text,
                    QC10_Text = Obj.QC10_Text,

                    QC1_Val = Obj.QC1_Val,
                    QC2_Val = Obj.QC2_Val,
                    QC3_Val = Obj.QC3_Val,
                    QC4_Val = Obj.QC4_Val,
                    QC5_Val = Obj.QC5_Val,
                    QC6_Val = Obj.QC6_Val,
                    QC7_Val = Obj.QC7_Val,
                    QC8_Val = Obj.QC8_Val,
                    QC9_Val = Obj.QC9_Val,
                    QC10_Val = Obj.QC10_Val
                };
                #endregion

                int? QcResult = DbCust.SaveShipmentQC_Details(QcParam);
                if (QcResult == 0 || QcResult == null)
                {
                    message.Append("Unable to update QC records");
                }
                else
                    message.Append("SUCCESS");
            }
            else
            {
                if (ShipmentId != null && ShipmentId > 0 && !Obj.PRODUCT.Contains("REV"))
                {
                    message.Append("SUCCESS");
                }
                else
                    message.Append("Record already exists");
            }
            return message.ToString();
        }
        else
            return "FAILURE";
    }
    catch (Exception ex)
    {
        log.LogError("bookingController/CacheOrderDetails Action", ex);
        return "FAILURE";
    }
}

Класс реализации

  public async Task<Int32> CacheOrderDetails(object o)
    {
       // return DbHelper.StoredProcWithParamsAsync<Int32>("SaveOrderDetails", o).FirstOrDefault();
        var res = await DbHelper.StoredProcWithParamsAsync<Int32>("SaveOrderDetails", o);
        return res.FirstOrDefault();
    }

Класс DB Helper

  public static async Task<List<T>> StoredProcWithParamsAsync<T>(string procname, dynamic parms, string connectionName = null)
    {
        using (SqlConnection connection = GetOpenConnectionAsync(connectionName))
        {
            var res= await connection.QueryAsync<T>(procname, (object)parms, commandType: CommandType.StoredProcedure);
            return res.ToList();
        }
    }

Объявление строки подключения

 public static SqlConnection GetOpenConnectionAsync(string name = null)
    {

        string connString = "";
        connString = ConfigurationManager.ConnectionStrings["connstr1"].ConnectionString;
        var connection = new SqlConnection(connString);
        connection.OpenAsync();
        return connection;
    }
...