Operations (Firebird)
RepoDB’s standard operations (Query, Insert, Merge, Update, Delete, etc.) all work against FbConnection once UseFirebird() has been called. BulkInsert, BulkMerge, BulkUpdate, BulkDelete and BulkDeleteByKey are provided by the separate RepoDb.Firebird.BulkOperations package, built on FbBatchCommand — the FirebirdSql.Data.FirebirdClient driver’s native ADO.NET batching API — via FirebirdCommandBatcher.
For BulkInsert, rows are written straight to the target table — unless FirebirdBulkImportIdentityBehavior.ReturnIdentity is requested, in which case a pseudo (staging) table is used instead so the generated identity values can be read back via an EXECUTE BLOCK cursor loop, correlated to the source rows by a client-assigned row-order column rather than by sorting the generated identities themselves.
For BulkDelete, BulkDeleteByKey, BulkMerge and BulkUpdate, a pseudo (staging) table is created — and dropped — for every call, indexed on the qualifier columns. The library writes to it via FirebirdCommandBatcher internally, then cascades the changes to the original table using the correct SQL statement.
Every pseudo table gets a per-call unique name, so unlike some other providers’ bulk-operations packages, concurrent callers writing against the same target table never race on a shared staging-table name.
The other bulk operations can be optimized further by targeting the underlying table indexes (via qualifiers). Pass a list of Field objects when calling the operations.
Pseudo Table Type
The FirebirdBulkImportPseudoTableType enum lets you choose between a Firebird GLOBAL TEMPORARY TABLE (Memory), an ordinary heap table (Physical), or let the library decide based on row count (Auto, the default — Physical at 5,000 rows or more, otherwise Memory).
Supported Objects
Below are the following objects supported by the bulk operations.
- System.DataTable
- System.Data.Common.DbDataReader
- IEnumerable<T>
- ExpandoObject
- IDictionary<string, object>
Operation SQL Statements
Once all the data is in the staging (pseudo) table, the correct SQL statement is used to cascade the changes towards the original table.
BulkInsert writes directly into the target table and skips the staging table entirely — unless
identityBehavioris set toReturnIdentity, in which case a staging table is used first (see above).
For BulkDelete / BulkDeleteByKey
> DELETE FROM "OriginalTable" T
> WHERE EXISTS (
> SELECT 1 FROM "PseudoTempTable" S
> WHERE T.QualifierField1 = S.QualifierField1 AND T.QualifierField2 = S.QualifierField2
> );
For BulkMerge
The exact shape depends on whether the identity column (if any) is itself a merge qualifier — see BulkMerge for the three variants (a single MERGE, or one of two EXECUTE BLOCK loop shapes).
For BulkUpdate
> MERGE INTO "OriginalTable" T USING "PseudoTempTable" S ON (T.QualifierField1 = S.QualifierField1 AND T.QualifierField2 = S.QualifierField2)
> WHEN MATCHED THEN
> UPDATE SET T.Field3 = S.Field3, T.Field4 = S.Field4;
Unlike BulkMerge, there is no
WHEN NOT MATCHEDbranch — staged rows with no matching target row are left as-is, not inserted.
Special Arguments
The arguments below are available on most operations.
| Argument | Description |
|---|---|
qualifiers | Defines the fields used to match existing rows. Defaults to the primary or identity column when not provided. |
identityBehavior | Via FirebirdBulkImportIdentityBehavior, controls whether the identity property is kept as-is, or whether newly generated identity values are returned back to the entities after BulkInsert or BulkMerge. |
pseudoTableType | Via FirebirdBulkImportPseudoTableType, controls the kind of staging table created — see Pseudo Table Type above. |
batchSize | Overrides the number of rows sent to the server per batch. When not set, all items are sent at once. |
BatchSize
All the provided bulk operations have a batchSize argument that lets you override the number of rows wired-up to the server per batch. By default it is null, meaning all items are sent together in one go.
Use this argument if you wish to optimize the operation based on certain situations.
- Network Latency
- Infrastructure
- No. of Columns
- Type of Data
SQL generation notes (standard operations)
FirebirdStatementBuilder generates Firebird-flavored SQL for every operation:
FIRST nfor top-N Query/Exists, andFIRST m SKIP nfor BatchQuery/skip-take queries — Firebird has noTOP/LIMITkeyword.- Insert/Merge read back the generated key via Firebird’s native
RETURNINGclause, which (unlike Oracle) surfaces directly as an ordinary single-row result set — no PL/SQL block or output-parameter wrapping needed. - Merge/MergeAll compile to
UPDATE OR INSERT INTO ... MATCHING (...) RETURNING ..., Firebird’s native single-statement upsert. When the identity column is itself a qualifier, anEXECUTE BLOCKis used instead (see FirebirdStatementBuilder for details), sinceMATCHINGcannot reliably match a not-yet-inserted row on its own not-yet-known identity value. - Truncate compiles to a plain
DELETE FROM t— Firebird has noTRUNCATE TABLEstatement (as of 5.0) — which does not reset aGENERATED ... AS IDENTITYcolumn’s next value.
No table hints
FirebirdDbSetting.AreTableHintsSupported is false. Passing a non-null hints argument to any operation throws a NotSupportedException.
One row per round trip for the *All operations
FirebirdDbSetting.IsMultiStatementExecutable is false — FbCommand cannot execute multiple statements in a single round trip. InsertAll, MergeAll and UpdateAll issue one statement per row instead of a single batched command; passing an explicit batchSize greater than 1 to any of them throws a NotSupportedException.
No session-wide scope identity
GetScopeIdentity/GetScopeIdentityAsync always throw NotSupportedException — Firebird has no construct equivalent to SQL Server’s SCOPE_IDENTITY() or MySQL’s LAST_INSERT_ID(). The generated key is already returned directly by Insert/Merge via RETURNING; query the underlying generator explicitly (e.g. GEN_ID(generator_name, 0)) if you need it out-of-band.
Async Methods
All the provided synchronous operations have an equivalent asynchronous (Async) counterpart.