migrating-oracle-to-postgres-data-access-code
Migrates .NET/C# data access code from Oracle to PostgreSQL (Npgsql). Replaces Oracle NuGet packages, rewrites OracleConnection/OracleCommand/OracleDataReader usage, fixes DbType mappings, updates stored procedure invocation patterns, and adapts connection string configuration. Use when migrating the application code layer of a .NET project during an Oracle-to-PostgreSQL database migration.
- License 许可
- MIT
- 最近更新
- 2026-11-14
- Stars
- ★ 4.1w
- Forks
- 5.4k
01 前言 Front Matter
- name
- migrating-oracle-to-postgres-data-access-code
- description
- Migrates .NET/C# data access code from Oracle to PostgreSQL (Npgsql). Replaces Oracle NuGet packages, rewrites OracleConnection/OracleCommand/OracleDataReader usage, fixes DbType mappings, updates stored procedure invocation patterns, and adapts connection string configuration. Use when migrating the application code layer of a .NET project during an Oracle-to-PostgreSQL database migration.
03 SKILL.md 正文
Migrating .NET Data Access Code from Oracle to PostgreSQL
Migrate the C# data access layer of a single .Postgres-copy project from Oracle (Oracle.ManagedDataAccess) to PostgreSQL (Npgsql). Work item by item through Reports/{ProjectName}/MigrationChecklist.md.
Prerequisites
- The
.Postgresproject copy exists (created in Phase 5 setup). Reports/{ProjectName}/MigrationChecklist.mdexists and is the source of truth for what to change.Reports/{ProjectName}/OracleRiskAnalysis.mdexists for cross-referencing behavioral differences.
Workflow
Progress:
- [ ] Step 1: Replace NuGet packages
- [ ] Step 2: Update connection string configuration
- [ ] Step 3: Rewrite ADO.NET type references
- [ ] Step 4: Fix DbType mappings
- [ ] Step 5: Migrate stored procedure invocation
- [ ] Step 6: Address Oracle-specific SQL and syntax
- [ ] Step 7: Build and verify
Step 1: Replace NuGet packages
In the .csproj of the .Postgres project:
- Remove:
Oracle.ManagedDataAccess.Core,Oracle.EntityFrameworkCore(and any otherOracle.*packages) - Add:
Npgsql(for ADO.NET) and/orNpgsql.EntityFrameworkCore.PostgreSQL(for EF Core) - Keep version pinning consistent with the target .NET version; do not introduce newer package versions than what the solution already uses for similar packages.
- If
System.Dataabstractions (IDbConnection,IDbCommand) are used project-wide, the surface-level code may need fewer changes — identify them first.
Step 2: Update connection string configuration
- Locate the Oracle connection string in
appsettings.json,appsettings.{env}.json,web.config,app.config, or environment variable configuration. - Replace with a Npgsql-compatible connection string:
Host=localhost;Port=5432;Database=mydb;Username=myuser;Password=mypassword - Do not hardcode credentials — use the same configuration mechanism already in use (e.g., environment variables, secrets manager,
IConfiguration). - Update any named connection string keys only if they were Oracle-specific (e.g.,
OracleConnection). Prefer keeping the same key name to minimize application config changes.
Step 3: Rewrite ADO.NET type references
Replace Oracle-specific ADO.NET types with Npgsql equivalents:
| Oracle type | Npgsql replacement |
|---|---|
OracleConnection |
NpgsqlConnection |
OracleCommand |
NpgsqlCommand |
OracleDataReader |
NpgsqlDataReader |
OracleDataAdapter |
NpgsqlDataAdapter |
OracleParameter |
NpgsqlParameter |
OracleTransaction |
NpgsqlTransaction |
OracleException |
NpgsqlException |
OracleDbType |
NpgsqlDbType (from NpgsqlTypes namespace) |
Update using directives accordingly (using Oracle.ManagedDataAccess.Client → using Npgsql).
If the codebase uses IDbConnection/IDbCommand abstractions registered via DI, update only the DI registration and connection string — the consuming code may not need changes.
Step 4: Fix DbType and NpgsqlDbType mappings
Oracle parameter types do not map 1:1 to Npgsql. Review every OracleParameter (now NpgsqlParameter) that sets an explicit type:
| Oracle type | Notes |
|---|---|
OracleDbType.Varchar2 |
Use NpgsqlDbType.Varchar or omit (Npgsql infers from value) |
OracleDbType.Clob |
Use NpgsqlDbType.Text |
OracleDbType.Number |
Use NpgsqlDbType.Numeric or NpgsqlDbType.Integer depending on precision |
OracleDbType.Date |
Use NpgsqlDbType.Date (date only) or NpgsqlDbType.Timestamp (if time component used) |
OracleDbType.TimeStamp |
Use NpgsqlDbType.Timestamp |
OracleDbType.RefCursor |
Use NpgsqlDbType.Refcursor — see Step 5 |
OracleDbType.Char |
Use NpgsqlDbType.Char |
For parameters where Oracle inferred the type from the value, Npgsql also infers — explicit type setting is often unnecessary and can be removed.
Step 5: Migrate stored procedure invocation
Oracle and PostgreSQL stored procedure invocation differ significantly:
- Command type: Retain
CommandType.StoredProcedurefor function calls. For procedures that useOUTparameters, PostgreSQL requiresCommandType.TextwithCALL proc_name(...)syntax in some versions of Npgsql — verify against the target Npgsql version. - RefCursor handling: Oracle returns ref cursors as output parameters; PostgreSQL returns them differently:
- For
RETURNS TABLE/RETURNS SETOF, useExecuteReader()directly — no cursor parameter needed. - For
RETURNS refcursor, call within a transaction, read the cursor name from the output parameter, then issueFETCH ALL IN "<cursor_name>". - Remove any Oracle-specific cursor-wrapping code (e.g.,
OracleRefCursor).
- For
- OUT parameters: PostgreSQL stored procedures use
INOUTor function return values. Verify parameter direction matches the migrated procedure signature. - Sequence
NEXTVAL: ReplaceSELECT {SEQUENCE}.NEXTVAL FROM DUALwithSELECT nextval('{sequence_name}'). - Named parameters: Npgsql uses
@param_name; Oracle used:param_name. Update all parameter name prefixes.
Step 6: Address Oracle-specific SQL and C# patterns
Review inline SQL strings and query builders for Oracle-specific constructs and replace:
| Oracle construct | PostgreSQL replacement |
|---|---|
ROWNUM <= n |
LIMIT n |
ROWNUM = 1 |
LIMIT 1 |
NVL(x, y) |
COALESCE(x, y) |
DECODE(expr, v1, r1, ...) |
CASE WHEN expr = v1 THEN r1 ... END |
SYSDATE / SYSTIMESTAMP |
NOW() or CURRENT_TIMESTAMP |
TO_CHAR(date, fmt) |
TO_CHAR(date, fmt) (mostly compatible; verify format strings) |
TO_DATE(str, fmt) |
TO_DATE(str, fmt) (verify format strings) |
TO_NUMBER(str) |
CAST(str AS NUMERIC) or str::NUMERIC |
| ` | |
DUAL table |
Remove FROM DUAL; PostgreSQL evaluates SELECT expr without a table |
CONNECT BY hierarchy |
Rewrite using recursive CTEs (WITH RECURSIVE) |
MERGE INTO |
Rewrite as INSERT ... ON CONFLICT DO UPDATE |
Empty string '' as NULL |
Oracle treats '' as NULL; PostgreSQL does not — check comparisons and IS NULL guards |
VARCHAR2 |
VARCHAR or TEXT |
Step 7: Build and verify
After addressing all checklist items:
- Run
dotnet buildon the.Postgresproject. Fix any remaining compilation errors. - Verify no Oracle-specific namespaces remain: search for
Oracle.ManagedDataAccess,OracleConnection,OracleCommand,:parampatterns. - Mark completed items in
Reports/{ProjectName}/MigrationChecklist.md.
EF Core projects
If the project uses Oracle.EntityFrameworkCore:
- Replace the provider registration in
DbContextconfiguration:.UseOracle(...)→.UseNpgsql(...) - Replace
OracleDbContextOptionsBuilderreferences. - Review
OnModelCreatingfor Oracle-specific configurations (e.g.,HasColumnType("NUMBER")→HasColumnType("numeric")). - Sequence configuration:
modelBuilder.HasSequence<int>("seq_name").StartsAt(1).IncrementsBy(1)syntax is compatible; verify column defaults referencing sequences. - Do not run EF Core migrations — schema is managed externally via DDL scripts (Phase 4).
Key Constraints
- Work only within the
.Postgrescopy — never modify the original Oracle-targeting project. - Keep to existing .NET and C# versions; do not introduce newer language or runtime features.
- Preserve comments and application logic; change only what is necessary for PostgreSQL compatibility.
- Oracle is the source of truth — behavioral differences must be documented as bug reports, not silently altered.
04 同仓库更多 Skills
supabase-rls-policies
Write, review, and test Supabase Row Level Security (RLS) policies so that one user cannot read or change another user's rows. Use when creating or changing tables, policies, views, or security definer functions in a Supabase project, when reviewing a migration that touches RLS, or when asked to prove user isolation with pgTAP tests that sign in as two users.
skill-distribution-audit
Audit a skill collection before release or investigate installer omissions, archived/template leakage, duplicate identities, and manifest drift. Reconcile the intended public source set, distribution manifest, and actual discovery output for a specified consumer version. Includes a deterministic set-comparison helper.
logicapps-custom-code-net10-migration
Migrate Azure Logic Apps Standard local-function custom-code projects from .NET 8 to .NET 10. Use for legacy Logic Apps custom-code workspace upgrades, project/package configuration, custom-worker settings, publication, and integrated VS Code debugging. Not for ordinary .NET applications, standalone Azure Functions, Consumption workflows, or cloud deployment.
winmd-api-search
Find and explore Windows desktop APIs. Use when building features that need platform capabilities — camera, file access, notifications, UI controls, AI/ML, sensors, networking, etc. Discovers the right API for a task and retrieves full type details (methods, properties, events, enumeration values).
resemble-detect
Deepfake detection and media safety — detect AI-generated audio, images, video, and text, trace synthesis sources, apply watermarks, verify speaker identity, and analyze media intelligence using Resemble AI
quality-playbook
Run a complete quality engineering audit on any codebase. Derives behavioral requirements from the code, generates spec-traced functional tests, runs a three-pass code review with regression tests, executes a multi-model spec audit (Council of Three), and produces a consolidated bug report with TDD-verified patches. Finds the 35% of real defects that structural code review alone cannot catch. Works with any language. Trigger on 'quality playbook', 'spec audit', 'Council of Three', 'fitness-to-purpose', or 'coverage theater'.