phnx47 / dapper-repositories

CRUD for Dapper

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Issue for MsSql in DapperRepository.BulkInsert and DapperRepository.BulkUpdate Items left behind because of exceededTimes Miscalculation

OscarHGallegoG opened this issue · comments

Issue

When we have a really long batch, the library often miscalculates the ammount of loops it has to make in order to BulkInsert/BulkUpdate

Explanation:

In both classes there's a formula wich calculates the ammount of times you have to iterate until you insert all items in a batch. The formula is has son variables:

  • totalInstances: Number of items (entities) to BulkInsert/BulkUpdate
  • properties: Number of properties in the entity to insert (Excluding Identity Columns)
  • exceededTimes: I assume is the number of iterations in order to execute the batch
  • Constant: 2099d which is the number of max parameters allowed by Sql Server See here
  • maxAllowedInstancesPerBatch: Self Explanatory
    An an example in c# is:
var totalInstances = 12760;
var properties = 46;
var exceededTimes = (int)Math.Ceiling(totalInstances * properties  / 2099d); //Returns: 280
var maxAllowedInstancesPerBatch = totalInstances / exceededTimes; //Returns: 45 (int), The double equivalent is 45.57142857

The preceding example shows the following:

  1. We are going to iterate 280 times because of the value of exceededTimes
  2. Each time we iterate, we will Take 45 instances from the batch to process

So in the end we will BulkInsert/BulkUpdate 280 * 45 = 12600
We are leaving out 12760 - 12600 = 160 items from the list without processing because of the difference between 45 and 45.57142857

The Solution

The solution is to not iterate using the exceededTimes variable but instead to iterate using another variable wich results from this calculation:

// 12760 / 45
var maxIterationCount = (int)Math.Ceiling((double)totalInstances / (double)maxAllowedInstancesPerBatch); //Returns: 284

now if we iterate 284 times, we will surely process all the items left because 284 * 45 = 12780 (20 more than needed)

The actual Code:

in BulkInsert.cs on lines 53 & 98 add the maxIterationCount Calculation, and change the iterator for i <= maxIterationCount;

    var maxIterationCount = (int)Math.Ceiling((double)totalInstances / (double)maxAllowedInstancesPerBatch);
    for (var i = 0; i <= maxIterationCount; i++)

in BulkUpdate.cs on lines 38 & 93 add the maxIterationCount Calculation, and change the iterator for i <= maxIterationCount;

    var maxIterationCount = (int)Math.Ceiling((double)totalInstances / (double)maxAllowedInstancesPerBatch);
    for (var i = 0; i <= maxIterationCount; i++)

Note:

I am creating this issue so I can submit a PullRequest with the actual bugfix

Released v1.24.1