0

So I have this problem where I want to post multiple http post using foreach loop. The problem is that the posted data is not in order, I mean the data is saved to the database but the data is not in order.

here is the sample data to be posted

    {
        "logsysid": 0,
        "CountMe": 1,
        "MachineNumber": 1,
        "EmpIDNo": "AAAAA",
        "IndRegID": "101",
        "InOut": 0,
        "verify": 0,
        "DateTimeRecord": "06/27/2022 6:48:47 AM",
        "machineLoc": null,
        "DateOnlyRecord": "/Date(1656259200000)/",
        "TimeOnlyRecord": "/Date(1656456527000)/",
        "errcode": 0,
        "errmessage": null
    },
    {
        "logsysid": 0,
        "CountMe": 2,
        "MachineNumber": 1,
        "EmpIDNo": "BBBBB",
        "IndRegID": "102",
        "InOut": 0,
        "verify": 0,
        "DateTimeRecord": "06/27/2022 6:48:52 AM",
        "machineLoc": null,
        "DateOnlyRecord": "/Date(1656259200000)/",
        "TimeOnlyRecord": "/Date(1656456532000)/",
        "errcode": 0,
        "errmessage": null
    },
    {
        "logsysid": 0,
        "CountMe": 3,
        "MachineNumber": 1,
        "EmpIDNo": "CCCCC",
        "IndRegID": "103",
        "InOut": 0,
        "verify": 0,
        "DateTimeRecord": "06/27/2022 6:49:06 AM",
        "machineLoc": null,
        "DateOnlyRecord": "/Date(1656259200000)/",
        "TimeOnlyRecord": "/Date(1656456546000)/",
        "errcode": 0,
        "errmessage": null
    }

here is my code

var ids = this.allData.map(data => data.CountMe).sort((a, b) => a - b);

ids.forEach((value, idx, arry) => {
  var parseDateTime = new Date(this.allData.find(x => x.CountMe === value).DateTimeRecord);
  var dateOnly = moment(parseDateTime).format('YYYY-MM-DD');
  var timeOnly = moment(parseDateTime).format('HH:mm:ss').toString();
  var dateTime = moment(parseDateTime).format('YYYY-MM-DDTHH:mm:ssZ');
  var empCode = this.allData.find(x => x.CountMe === value).EmpIDNo;
  var logType = this.allData.find(x => x.CountMe === value).InOut;

  const body = {
    empcode: empCode,
    logtype: logType,
    trndate: dateOnly,
    trntime: timeOnly,
    svrtime: dateTime
  }

  this.spinner.show();
  this.apiservice.insertLogs(body).subscribe((data: any) => {
    var result = data;
    if (result == 1) {
      if (idx === arry.length - 1) {
        $('#dtrTable').DataTable().clear().destroy();
        this.allData = [];
        this.toastr.success("Successfully uploaded logs to server", '', { timeOut: 10000 });
      }
    } else if (result == 0) {
      this.toastr.error("Error occured!")
    }
    this.spinner.hide();
  },
    (error: any) => {
      this.toastr.error(error.message);
      console.log(error.message);
      this.spinner.hide();
    })
});

As you can see I sorted the data by CountMe. EmpIDNo AAAAA should be the first to be saved in the database. But the data that is saved is ordered randomly, like EmpIDNo BBBBB is saved first. The table has a column name ID which is the Primary Key with auto increment. So EmpIDNo AAAAA should have the ID 1, BBBBB should have 2 etc. How to fix this?

This is my controller.cs

    [HttpPost("insertdtr")]
    [Authorize]
    public ActionResult<int> InsertDtr(Dtr model)
    {
        int result = 0;
        try
        {
            using (dbContext _dbcontext = new())
            {
                Dtr obj = new()
                {
                    Empcode = model.Empcode,
                    Logtype = model.Logtype,
                    Trndate = model.Trndate,
                    Trntime = model.Trntime,
                    SvrTime = model.SvrTime
                };

                _dbcontext.Dtrs.Add(obj);
                _dbcontext.SaveChanges();

                result = 1;
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
            result = 0;
        }

        return result;
    }
Rak
  • 139
  • 5
  • 20
  • the javascript `forEach` loop will not wait for each iteration to complete before kicking off the next. use a `for...of loop` instead. https://stackoverflow.com/questions/37576685/using-async-await-with-a-foreach-loop – Lee Jun 29 '22 at 07:56
  • What do you mean `order`? Tables have no implicit order, even when they have a clustered key. Query results have none either, unless imposed by an `ORDER BY` clause. Without it, the server is free to use the cheapest way possible to return results. – Panagiotis Kanavos Jun 29 '22 at 07:56
  • 4
    Instead of posting records one by one, post an array of all the records at once as an array and accept a `Dtr[]` array on the other side. Add all of them to the context then call `SaveChanges` once. This will insert all records in a single internal transaction. Instead of N network and database requests, you'll have only a single request and a single DB operation – Panagiotis Kanavos Jun 29 '22 at 07:57

1 Answers1

1

What you just need to do is create an array and post it directly and if your model is same than you also need not to create a new list and add objects iteratively. All your records will be stored in proper sequence and entity framework will do the job for you.

[HttpPost("insertdtr")]
[Authorize]
public ActionResult<int> InsertDtr(List<Dtr> list)
{
    int result = 0;
    try
    {
        using (dbContext _dbcontext = new())
        {

            _dbcontext.Dtrs.AddRange(list);
            _dbcontext.SaveChanges();

            result = 1;
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.Message);
        result = 0;
    }

    return result;
}
  • this works but the data is still uploaded randomly. But thanks to this answer I got an idea, I loop each list and use `Add` rather than using `AddRange` – Rak Jun 30 '22 at 00:55