You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Issue:public static Task BulkInsertAsync<T>(this DbContext context, IEnumerable<T> entities, BulkConfig? bulkConfig = null, Action<decimal>? progress = null, Type? type = null, CancellationToken cancellationToken = default) where T : class Iterates over IEnumerable<T> entities multiple times
Expected: Iterates over IEnumerable<T> only once.
Actual: Appears to Iterate over the IEnumerable multiple times (number of iterations grows with the number of items provided by the IEnumerable<T> (see test output for iteration and item creation counts)
Effect: Lazily Loaded IEnumerable<T> sources (i.e. code using yield return) has unanticipated effects:
The source is read multiple times, resulting in more objects than necessary being instantiated.
If used in conjunction with Guid.NewGuid() multiple copies of the same data are instantiated with different keys. this can result in subsequent insertions raising Referential Integrity Errors. (not depicted in test)
Remarks:
Looks like this was introduced in commit: 27407aae3e24ee337fc916bd1d653045c54cb066
Signature was changed from IList<T> to IEnumerable<T> but IEnumerable<T> was treated as an IList<T> of a known length rather than an IEnumerable<T> source of unknown length.
Code path at multiple points:
Attempts to get the length of the IEnumerable<T> (.Count())
Checks to see if there are any records (.Any())
Assigned the entirety of the IEnumerable<T> to memory (.ToList())
Hi Boris (and Team)
Loving this library!
However, ran into this today.
Issue:
public static Task BulkInsertAsync<T>(this DbContext context, IEnumerable<T> entities, BulkConfig? bulkConfig = null, Action<decimal>? progress = null, Type? type = null, CancellationToken cancellationToken = default) where T : class
Iterates overIEnumerable<T>
entities multiple timesExpected: Iterates over
IEnumerable<T>
only once.Actual: Appears to Iterate over the IEnumerable multiple times (number of iterations grows with the number of items provided by the
IEnumerable<T>
(see test output for iteration and item creation counts)Effect: Lazily Loaded
IEnumerable<T>
sources (i.e. code usingyield return
) has unanticipated effects:Guid.NewGuid()
multiple copies of the same data are instantiated with different keys. this can result in subsequent insertions raising Referential Integrity Errors. (not depicted in test)Remarks:
27407aae3e24ee337fc916bd1d653045c54cb066
IList<T>
toIEnumerable<T>
butIEnumerable<T>
was treated as anIList<T>
of a known length rather than anIEnumerable<T>
source of unknown length.IEnumerable<T>
(.Count()
).Any()
)IEnumerable<T>
to memory (.ToList()
)Notes:
Work Around:
List<T>
note: Memory Intensive with large data sets.Test Outputs:
Test Reproduction (Should drop into the
EfCore.BulkExtensions.Tests.csproj
)Suggestions for fix:
Note: Apologies, I haven't got the capacity to provide a PR with fixes at the moment.
IEnumerable<T>
is iterated once.IEnumerable<T>
to count during execution..Any()
against theIEnumerable<T>
instead optimistically execute the insertion, finishing if there are noT
s.ToList()
on theIEnumerable<T>
The text was updated successfully, but these errors were encountered: