C # Web API Несколько вызовов для метода, который пишет в базу данных - PullRequest
0 голосов
/ 13 января 2019

Я надеюсь, что кто-то может помочь мне написать этот метод лучше. Метод работает как есть, пока несколько пользователей не нажмут метод одновременно. Я начал работать над использованием async / await, но я не знаю, будет ли это работать для меня. Самая большая проблема заключается в том, что у нас есть промежуточная / рабочая таблица, в которую мы сохраняем, а затем выполняем хранимую процедуру для таблицы, которая выполняет некоторые действия и очищает таблицу после ее завершения. Данные в таблице зависят от пользователя, поэтому нам нужны только данные для пользователя, выполняющего хранимую процедуру. Если туда попадают другие данные, они все портят. Вот почему у меня есть проверка, чтобы убедиться, что таблица пуста, прежде чем мы продолжим.

Короче говоря, как я могу заставить этот метод работать действительно RESTful способом и обеспечить масштабируемость для многих пользователей?

[HttpPost, Route("api/SubmitOrder")]
public IHttpActionResult SubmitOrderEntry([FromBody] OrderRequest request)
{
    var profileObjs = OrderEntities.Set<OrderStaging>();
    foreach (var s in request.Items)
    {
        OrderStaging orderObj = new OrderStaging();

        orderObj.OrderName = request.OrderName;
        orderObj.OrderDescription = request.OrderDescription;
        orderObj.OrderComments = request.Comments;
        orderObj.EnteredBy = request.EnteredBy;
        //and many more

        profileObjs.Add(orderObj);
    }

    try
    {
        bool tableEmpty = false;
        int count = 0;
        int countMax = 180;

        while (!tableEmpty && count < countMax)
        {
            count++;
            if (!OrderEntities.OrderStagings.Any())
            {
                tableEmpty = true;
            }
            else
            {
                System.Threading.Thread.Sleep(5000);
            }
        }

        if (tableEmpty)
        {
            OrderEntities.Configuration.EnsureTransactionsForFunctionsAndCommands = false;
            OrderEntities.Database.CommandTimeout = 180;
            OrderEntities.SaveChanges();

            if (request.Pending)
            {
                var result = OrderEntities.SPPENDING();
                var firstRow = result.FirstOrDefault();
                String[] returnValue = new String[] { firstRow.TransactionID, firstRow.ExternalOrderID };
                return Ok(returnValue);
            }
            else
            {
                var result = OrderEntities.SPORDER();
                var firstRow = result.FirstOrDefault();
                String[] returnValue = new String[] { firstRow.TransactionID, firstRow.ExternalOrderID };
                return Ok(returnValue);
            }
        }

        return Content(HttpStatusCode.BadRequest, "SQL Server Exception");
    }
    catch (Exception e)
    {
        Console.WriteLine(e.ToString());
        return Content(HttpStatusCode.BadRequest, "SQL Server Exception");
    }
} 

1 Ответ

0 голосов
/ 14 января 2019

Вы, вероятно, захотите переосмыслить свой подход здесь. Похоже, у вас есть существующее решение, которое включает в себя хранимую процедуру, которая обрабатывает эти промежуточные записи и, вероятно, занимает немного времени для завершения. Sproc предполагает, что все промежуточные записи относятся к задаче, для которой он предназначен. Очередь нескольких запросов во время работы sproc приведет к проблемам.

Первое, что вы должны рассмотреть, это разделить вызовы на две части: 1. Подготовьте данные. 2. Опрос на результат. Не заставляйте вызов API сидеть и ждать завершения хранимой процедуры, передавайте ей результат, указывающий, что данные были успешно созданы или нет, и клиентский код может быть передан в часть # 2, которая является опросом для результат для этой работы. Опрос может быть для отдельного идентификатора задания или на основе даты / времени последнего опроса и записей опроса, измененных с этой даты / времени. (Это может позволить клиенту «видеть» задания, запущенные другими пользователями, если применимо)

Что касается вашей промежуточной процедуры и хранимой процедуры, идентификатор работы должен быть добавлен в промежуточную таблицу. Каждой строке в промежуточной таблице присваивается идентификатор задания, в записи задания отслеживаются некоторые основные сведения о запросе, в том числе: когда он был запущен? Кто это начал? Это завершено? Каков его статус? (поставлен в очередь, запущен, завершен, потерпел неудачу и т. д.) Какова была причина отказа? (если применимо) Хранимая процедура должна быть запущена с идентификатором задания или запросить любые незапущенные задания и обработать промежуточные записи для этого задания или группы заданий. Когда сохраненный процесс завершает обработку набора записей, он обновляет строку задания и удаляет промежуточные записи. Я бы даже подумал оставить чистку промежуточных записей для запланированной задачи, которая выполняется ежедневно в нерабочее время, чтобы избежать ненужных блокировок в базе данных на этой таблице. (Удалите промежуточные строки и / или задания, которые выполнялись / не выполнялись каждую ночь.)

Подумайте о том, чтобы спроектировать системы для масштабирования нескольких запросов, которые могут быть либо успешно обработаны одновременно, либо чтобы все этапы процесса могли идентифицироваться и обрабатываться по порядку, но не задерживать очередь одного запроса до тех пор, пока предыдущий не завершится.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...