Search code examples
c#databaseentity-frameworkentity-framework-coreefcore.bulkextensions

BulkInsertAsync from EFCore.BulkExtensions doesn't seem to insert anything


I'm using EFCore.BulkExtensions to insert batches of, at most, 100,000 records into a database.

My issue is, for some reason, BulkInsertAsync does not insert any records to the DB. I understand it's an asynchronous call, but I've waited half an hour and no data was inserted. The regular, synchronous BulkInsert call works, but is extremely suboptimal since it hogs a ton of process time.

Does anyone have any idea why BulkInsertAsync doesn't work in this context, but BulkInsert does?

Here is the relevant code, which marshals binary data (transmitted from another machine) into a C struct, adds that C struct to a list, and then bulk-inserts the list into the database.

            IList<object> records = new List<object>();
            using (var db = new RecordContext())
            {
                // keep going until we process all the data; numRecs is at most 100,000
                for (int i = 0; i < numRecs; i++)
                {
                    // marshal the data into the struct and map it to its database struct
                    var tempStruct = Marshal.PtrToStructure<T>(dataPtr);
                    records.Add(tempStruct);
                    dataPtr += Marshal.SizeOf<T>();
                }
                db.BulkInsertAsync(records);
            }

Here is the relevant context code:

    public class RecordContext : DbContext
    {
        public RecordContext() : base(GetOptions()) 
        { 
            // disable change tracking for performance
            ChangeTracker.AutoDetectChangesEnabled = false;
        }

        private static DbContextOptions GetOptions()
        {
            return SqlServerDbContextOptionsExtensions.UseSqlServer(new DbContextOptionsBuilder(), new Settings().recordsConnectionString).Options;
        }
        // . . .
    }

The following connection string is passed in from settings: Data Source=localhost;Integrated Security=True;TrustServerCertificate=True;ApplicationIntent=ReadWrite;Initial Catalog=Records


Solution

  • The method should do something - if you await it.

    So instead of: db.BulkInsertAsync(records); do: await db.BulkInsertAsync(records);

    Essentially, you told it to execute an async task, then you exited the method that created / owned the task by not calling await, causing the task to be abandoned. There's some subtle magic going on with the async tasks, LOL.