{"id":28297181,"url":"https://github.com/phenx/phenx.entityframeworkcore.bulkinsert","last_synced_at":"2026-01-19T22:10:34.205Z","repository":{"id":294487824,"uuid":"965481294","full_name":"PhenX/PhenX.EntityFrameworkCore.BulkInsert","owner":"PhenX","description":"Super fast bulk insertion for Entity Framework Core on SQL Server, PostgreSQL, Sqlite, MySQL and Oracle","archived":false,"fork":false,"pushed_at":"2025-09-29T16:43:34.000Z","size":1556,"stargazers_count":125,"open_issues_count":3,"forks_count":7,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-10-11T00:23:16.369Z","etag":null,"topics":["bulk","bulk-insert","efcore","entity-framework-core","mysql","postgresql","sql","sqlbulkcopy","sqlite","sqlserver"],"latest_commit_sha":null,"homepage":"https://phenx.github.io/PhenX.EntityFrameworkCore.BulkInsert","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/PhenX.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":"CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":["PhenX"],"patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"lfx_crowdfunding":null,"polar":null,"buy_me_a_coffee":null,"thanks_dev":null,"custom":null}},"created_at":"2025-04-13T09:04:44.000Z","updated_at":"2025-09-14T14:22:25.000Z","dependencies_parsed_at":"2025-05-20T17:32:10.034Z","dependency_job_id":"89ee77f8-1912-400a-83b2-9643ed91ffa9","html_url":"https://github.com/PhenX/PhenX.EntityFrameworkCore.BulkInsert","commit_stats":null,"previous_names":["phenx/phenx.entityframeworkcore.bulkinsert"],"tags_count":14,"template":false,"template_full_name":null,"purl":"pkg:github/PhenX/PhenX.EntityFrameworkCore.BulkInsert","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PhenX%2FPhenX.EntityFrameworkCore.BulkInsert","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PhenX%2FPhenX.EntityFrameworkCore.BulkInsert/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PhenX%2FPhenX.EntityFrameworkCore.BulkInsert/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PhenX%2FPhenX.EntityFrameworkCore.BulkInsert/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/PhenX","download_url":"https://codeload.github.com/PhenX/PhenX.EntityFrameworkCore.BulkInsert/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PhenX%2FPhenX.EntityFrameworkCore.BulkInsert/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279018619,"owners_count":26086404,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-14T02:00:06.444Z","response_time":60,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bulk","bulk-insert","efcore","entity-framework-core","mysql","postgresql","sql","sqlbulkcopy","sqlite","sqlserver"],"created_at":"2025-05-23T01:17:47.583Z","updated_at":"2025-10-14T09:41:08.873Z","avatar_url":"https://github.com/PhenX.png","language":"C#","readme":"# PhenX.EntityFrameworkCore.BulkInsert\n\nA high-performance, provider-agnostic bulk insert extension for Entity Framework Core 8+. Supports SQL Server, PostgreSQL, SQLite, MySQL and Oracle.\n\nIts main purpose is to provide a fast way to perform simple bulk inserts in Entity Framework Core applications.\n\n## Why this library?\n\n- **Performance**: It is designed to be fast and memory efficient, making it suitable for high-performance applications.\n- **Provider-agnostic**: It works with multiple database providers (SQL Server, PostgreSQL, SQLite and MySQL), allowing you to use it in different environments without changing your code.\n- **Simplicity**: The API is simple and easy to use, making it accessible for developers of all skill levels.\n\nFor now, it does not support navigation properties, complex types, owned types, shadow properties, or inheritance,\nbut they are in [the roadmap](#roadmap).\n\n## Packages\n\n| Package Name                                      | Description    | NuGet Link                                                                                                                                                                     |\n|---------------------------------------------------|----------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| `PhenX.EntityFrameworkCore.BulkInsert.SqlServer`  | For SQL Server | [![NuGet](https://img.shields.io/nuget/v/PhenX.EntityFrameworkCore.BulkInsert.SqlServer.svg)](https://www.nuget.org/packages/PhenX.EntityFrameworkCore.BulkInsert.SqlServer)   |\n| `PhenX.EntityFrameworkCore.BulkInsert.PostgreSql` | For PostgreSQL | [![NuGet](https://img.shields.io/nuget/v/PhenX.EntityFrameworkCore.BulkInsert.PostgreSql.svg)](https://www.nuget.org/packages/PhenX.EntityFrameworkCore.BulkInsert.PostgreSql) |\n| `PhenX.EntityFrameworkCore.BulkInsert.Sqlite`     | For SQLite     | [![NuGet](https://img.shields.io/nuget/v/PhenX.EntityFrameworkCore.BulkInsert.Sqlite.svg)](https://www.nuget.org/packages/PhenX.EntityFrameworkCore.BulkInsert.Sqlite)         |\n| `PhenX.EntityFrameworkCore.BulkInsert.MySql`      | For MySql      | [![NuGet](https://img.shields.io/nuget/v/PhenX.EntityFrameworkCore.BulkInsert.Sqlite.svg)](https://www.nuget.org/packages/PhenX.EntityFrameworkCore.BulkInsert.MySql)          |\n| `PhenX.EntityFrameworkCore.BulkInsert.Oracle`     | For Oracle      | [![NuGet](https://img.shields.io/nuget/v/PhenX.EntityFrameworkCore.BulkInsert.Oracle.svg)](https://www.nuget.org/packages/PhenX.EntityFrameworkCore.BulkInsert.Oracle)         |\n| `PhenX.EntityFrameworkCore.BulkInsert`            | Common library | [![NuGet](https://img.shields.io/nuget/v/PhenX.EntityFrameworkCore.BulkInsert.svg)](https://www.nuget.org/packages/PhenX.EntityFrameworkCore.BulkInsert)                       |\n\n## Installation\n\nInstall the NuGet package for your database provider:\n\n```shell\n# For SQL Server\nInstall-Package PhenX.EntityFrameworkCore.BulkInsert.SqlServer\n\n# For PostgreSQL\nInstall-Package PhenX.EntityFrameworkCore.BulkInsert.PostgreSql\n\n# For SQLite\nInstall-Package PhenX.EntityFrameworkCore.BulkInsert.Sqlite\n\n# For MySql\nInstall-Package PhenX.EntityFrameworkCore.BulkInsert.MySql\n\n# For Oracle\nInstall-Package PhenX.EntityFrameworkCore.BulkInsert.Oracle\n```\n\n## Usage\n\nRegister the bulk insert provider in your `DbContextOptions`:\n\n```csharp\nservices.AddDbContext\u003cMyDbContext\u003e(options =\u003e\n{\n    options\n        // .UseSqlServer(connectionString) // or UseNpgsql or UseSqlite, as appropriate\n\n        .UseBulkInsertPostgreSql()\n        // OR\n        .UseBulkInsertSqlServer()\n        // OR\n        .UseBulkInsertSqlite()\n        // OR\n        .UseBulkInsertMySql()\n        // OR\n        .UseBulkInsertOracle()\n        ;\n});\n```\n\n### Very basic usage\n\n```csharp\n// Asynchronously\nawait dbContext.ExecuteBulkInsertAsync(entities);\n\n// Or synchronously\ndbContext.ExecuteBulkInsert(entities);\n```\n\n### Bulk insert with options\n\n```csharp\n// Common options\nawait dbContext.ExecuteBulkInsertAsync(entities, options =\u003e\n{\n    options.BatchSize = 1000; // Set the batch size for the insert operation, the default value is different for each provider\n});\n\n// Provider specific options, when available, example for SQL Server\nawait dbContext.ExecuteBulkInsertAsync(entities, (SqlServerBulkInsertOptions o) =\u003e // \u003c\u003c\u003c here specify the SQL Server options class\n{\n    options.EnableStreaming = true; // Enable streaming for SQL Server\n});\n\n// Provider specific options, supporting multiple providers\nawait dbContext.ExecuteBulkInsertAsync(entities, o =\u003e\n{\n    o.MoveRows = true;\n\n    if (o is SqlServerBulkInsertOptions sqlServerOptions)\n    {\n        sqlServerOptions.EnableStreaming = true;\n    }\n    else if (o is MySqlBulkInsertOptions mysqlOptions)\n    {\n        mysqlOptions.BatchSize = 1000;\n    }\n});\n```\n\n### Returning inserted entities\n\n```csharp\nawait dbContext.ExecuteBulkInsertReturnEntitiesAsync(entities);\n```\n\n### Conflict resolution / merge / upsert\n\nConflict resolution works by specifying columns that should be used to detect conflicts and the action to take when\na conflict is detected (e.g., update existing rows), using the `onConflict` parameter.\n\n * The conflicting columns are specified with the `Match` property and must have a unique constraint in the database.\n * The action to take when a conflict is detected is specified with the `Update` property. If not specified, the default action is to do nothing (i.e., skip the conflicting rows).\n * You can also specify the condition for the update action using either the `Where` or the `RawWhere` property. If not specified, the update action will be applied to all conflicting rows.\n\n```csharp\nawait dbContext.ExecuteBulkInsertAsync(entities, onConflict: new OnConflictOptions\u003cTestEntity\u003e\n{\n    Match = e =\u003e new\n    {\n        e.Name,\n        // ...other columns to match on\n    },\n\n    // Optional: specify the update action, if not specified, the default action is to do nothing\n    // Excluded is the row being inserted which is in conflict, and Inserted is the row already in the database.\n    Update = (inserted, excluded) =\u003e new TestEntity\n    {\n        Price = inserted.Price // Update the Price column with the new value\n    },\n\n    // Optional: specify the condition for the update action\n    // Excluded is the row being inserted which is in conflict, and Inserted is the row already in the database.\n    // Using raw SQL condition\n    RawWhere = (insertedTable, excludedTable) =\u003e $\"{excludedTable}.some_price \u003e {insertedTable}.some_price\",\n\n    // OR using a lambda expression\n    Where = (inserted, excluded) =\u003e excluded.Price \u003e inserted.Price,\n});\n```\n\n## Roadmap\n\n- [ ] [Add support for navigation properties](https://github.com/PhenX/PhenX.EntityFrameworkCore.BulkInsert/issues/2)\n- [x] [Add support for complex types](https://github.com/PhenX/PhenX.EntityFrameworkCore.BulkInsert/issues/3)\n- [x] Add support for owned types\n- [ ] Add support for shadow properties\n- [ ] Add support for TPT (Table Per Type) inheritance\n- [ ] Add support for TPC (Table Per Concrete Type) inheritance\n- [ ] Add support for TPH (Table Per Hierarchy) inheritance\n\n## Benchmarks\n\nBenchmark projects are available in the [`tests/PhenX.EntityFrameworkCore.BulkInsert.Benchmark`](tests/PhenX.EntityFrameworkCore.BulkInsert.Benchmark/LibComparator.cs) directory.\nRun them to compare performance with raw bulk insert methods and other libraries (https://github.com/borisdj/EFCore.BulkExtensions\nand https://entityframework-extensions.net/bulk-extensions), using optimized configuration (local Docker is required).\n\nLegend :\n * `PhenX_EntityFrameworkCore_BulkInsert`: this library\n * `RawInsert`: naive implementation without any library, using the native provider API (SqlBulkCopy for SQL Server, BeginBinaryImport for PostgreSQL, raw inserts for SQLite)\n * `Z_EntityFramework_Extensions_EFCore`: https://entityframework-extensions.net/bulk-extensions\n * `EFCore_BulkExtensions`: https://github.com/borisdj/EFCore.BulkExtensions\n * `Linq2Db`: https://github.com/linq2db/linq2db\n\nPostgreSQL results with 500 000 rows :\n\n![bench-postgresql.png](https://raw.githubusercontent.com/PhenX/PhenX.EntityFrameworkCore.BulkInsert/refs/heads/main/images/bench-postgresql.png)\n\nSQLite results with 500 000 rows :\n\n![bench-sqlite.png](https://raw.githubusercontent.com/PhenX/PhenX.EntityFrameworkCore.BulkInsert/refs/heads/main/images/bench-sqlite.png)\n\nMySQL results with 500 000 rows :\n\n![bench-mysql.png](https://raw.githubusercontent.com/PhenX/PhenX.EntityFrameworkCore.BulkInsert/refs/heads/main/images/bench-mysql.png)\n\nWhere are the SQL Server and Oracle benchmarks? [You can run them yourself](https://www.google.com/search?q=dewitt+clause).\n\n## Contributing\n\nContributions are welcome! Please open issues or submit pull requests for bug fixes, features, or documentation improvements.\n\n## License\n\nMIT License. See [LICENSE](LICENSE) for details.\n","funding_links":["https://github.com/sponsors/PhenX"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fphenx%2Fphenx.entityframeworkcore.bulkinsert","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fphenx%2Fphenx.entityframeworkcore.bulkinsert","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fphenx%2Fphenx.entityframeworkcore.bulkinsert/lists"}