PhenX.EntityFrameworkCore.BulkInsert

repository·main·Indexed 41 days ago

https://github.com/phenx/phenx.entityframeworkcore.bulkinsert

A high-performance, provider-agnostic extension for EF Core 8+ designed for memory-efficient bulk inserts. Supports SQL Server, PostgreSQL, SQLite, MySQL, and Oracle. Features include conflict resolution (upsert/merge), the ability to return inserted entities via ExecuteBulkInsertReturnEntities, and OpenTelemetry instrumentation.

Tokens
5.2K
Snippets
18
Records
22
Agent score
99%

What's inside PhenX BulkInsert

  1. Overview of PhenX BulkInsert

    main
    PhenX BulkInsert is a high-performance, provider-agnostic bulk insert extension designed for Entity Framework Core 8+. It provides significantly faster data insertion compared to standard SaveChanges() by using optimized SQL generation and batching. It is designed to be memory efficient with low allocations and low garbage collection pressure.
  2. Understand the limitations of PhenX.EntityFrameworkCore.BulkInsert

    main

    When using PhenX.EntityFrameworkCore.BulkInsert, be aware of the following unsupported features:

    • Navigation properties: You can only insert simple entities. The library does not support inserting entities that contain navigation properties (relationships).
    • Change tracking: The library does not track changes to the entities being inserted. Consequently, DbContext.ChangeTracker will not reflect changes to these entities after the bulk insert operation is complete.
    • Inheritance: The library does not support entity types using inheritance hierarchies (such as TPT, TPH, or TPC). You must insert entities of a single, concrete type.
  3. Install PhenX.EntityFrameworkCore.BulkInsert for your database provider

    main

    Install the specific NuGet package corresponding to your database provider to enable bulk insert capabilities. You should also install the common library PhenX.EntityFrameworkCore.BulkInsert if required by your project structure, though the provider packages typically pull in necessary dependencies.

    # For SQL Server
    Install-Package PhenX.EntityFrameworkCore.BulkInsert.SqlServer
    
    # For PostgreSQL
    Install-Package PhenX.EntityFrameworkCore.BulkInsert.PostgreSql
    
    # For SQLite
    Install-Package PhenX.EntityFrameworkCore.BulkInsert.Sqlite
    
    # For MySql
    Install-Package PhenX.EntityFrameworkCore.BulkInsert.MySql
    
    # For Oracle
    Install-Package PhenX.EntityFrameworkCore.BulkInsert.Oracle
    
    # For OpenTelemetry instrumentation
    Install-Package PhenX.EntityFrameworkCore.BulkInsert.OpenTelemetry
  4. Register the bulk insert provider in DbContextOptions

    main

    To use the library, you must register the bulk insert provider within your DbContext configuration using the extension methods provided by the specific provider package. This is done during service registration (e.g., in Startup.cs or Program.cs).

    services.AddDbContext<MyDbContext>(options =>
    {
        options
            // Choose the method corresponding to your provider:
            .UseBulkInsertPostgreSql()
            // OR
            .UseBulkInsertSqlServer()
            // OR
            .UseBulkInsertSqlite()
            // OR
            .UseBulkInsertMySql()
            // OR
            .UseBulkInsertOracle()
            ;
    });
  5. Configure OpenTelemetry instrumentation

    main

    Register the instrumentation within your OpenTelemetry TracerProvider configuration by calling AddPhenXEntityFrameworkCoreBulkInsertInstrumentation(). This allows the library to automatically track bulk insert operations as Activities.

    using OpenTelemetry.Trace;
    
    builder.Services.AddOpenTelemetry()
        .WithTracing(tracing => tracing
            .AddAspNetCoreInstrumentation()
            .AddPhenXEntityFrameworkCoreBulkInsertInstrumentation() // <-- add this
            .AddOtlpExporter()
        );
  6. Configure the DbContext for Bulk Insert

    main

    To use the bulk insert functionality, you must register the appropriate provider in your DbContext configuration using the UseBulkInsert... extension methods. This should be called alongside your standard database provider (e.g., UseSqlServer, UseNpgsql, etc.) during service registration.

    services.AddDbContext<MyDbContext>(options =>
    {
        options
            // .UseSqlServer(connectionString) // or UseNpgsql or UseSqlite, as appropriate
    
            .UseBulkInsertPostgreSql()
            // OR
            .UseBulkInsertSqlServer()
            // OR
            .UseBulkInsertSqlite()
            // OR
            .UseBulkInsertMySql()
            // OR
            .UseBulkInsertOracle()
            ;
    });
  7. Enable bulk insert logging

    main

    Bulk insert operations emit EF Core-style logs. To see them, ensure a loggerFactory is configured on your DbContext options.

    Key log events:

    • 1004 (Information): Bulk insert completed, including elapsed time and destination table.
    • 1005 (Debug): Auxiliary SQL commands (like temporary table DDL) executed by the library.
    services.AddDbContext<MyDbContext>(options =>
    {
        options
            .UseSqlite(connectionString)
            .UseLoggerFactory(loggerFactory)
            .UseBulkInsertSqlite();
    });
  8. Monitor Bulk Insert via Logging

    main

    Bulk insert operations emit EF Core-style logs. To see these, ensure a loggerFactory is configured in your DbContext setup.

    Key log events:

    • 1004 (Information): Bulk insert completed, including elapsed time and destination table.
    • 1005 (Debug): Auxiliary SQL commands executed by the library (e.g., temporary table creation).
    services.AddDbContext<MyDbContext>(options =>
    {
        options
            .UseSqlite(connectionString)
            .UseLoggerFactory(loggerFactory)
            .UseBulkInsertSqlite();
    });
  9. Subscribe to the PhenX.EntityFrameworkCore.BulkInsert Activity Source

    main

    If you require lower-level access to traces, you can subscribe directly to the activity source using the name PhenX.EntityFrameworkCore.BulkInsert via an ActivityListener.

    using System.Diagnostics;
    
    ActivitySource.AddActivityListener(new ActivityListener
    {
        ShouldListenTo = source => source.Name == "PhenX.EntityFrameworkCore.BulkInsert",
        Sample = (ref ActivityCreationOptions<ActivityContext> _) => ActivitySamplingResult.AllDataAndRecorded,
        ActivityStarted = activity => Console.WriteLine($"Started: {activity.DisplayName}"),
        ActivityStopped = activity => Console.WriteLine($"Stopped: {activity.DisplayName} ({activity.Duration})"),
    });
  10. Configure Bulk Insert Options

    main

    You can customize the behavior of bulk inserts by passing an Action<BulkInsertOptions<T>> to the execution methods. Options can be common across providers or specific to a provider (e.g., SqlServerBulkInsertOptions).

    // Common options
    await dbContext.ExecuteBulkInsertAsync(entities, options =>
    {
        options.BatchSize = 1000;
    });
    
    // Provider specific options (SQL Server)
    await dbContext.ExecuteBulkInsertAsync(entities, (SqlServerBulkInsertOptions o) => 
    {
        o.EnableStreaming = true;
    });
    
    // Supporting multiple providers in one call
    await dbContext.ExecuteBulkInsertAsync(entities, o =>
    {
        o.MoveRows = true;
    
        if (o is SqlServerBulkInsertOptions sqlServerOptions)
        {
            sqlServerOptions.EnableStreaming = true;
        }
        else if (o is MySqlBulkInsertOptions mysqlOptions)
        {
            mysqlOptions.BatchSize = 1000;
        }
    });