首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> DB2 資料庫 >> DB2 教學

Visual C# 連接 DB2 實戰:OLE DB Provider 架構下的數據訪問完整指南

     編輯:DB2 教學

技術棧演進與版本定位

時代數據訪問技術DB2 驅動現狀
.NET Framework 1.x (VS.NET 2002/2003)ODBC .NET ProviderIBM DB2 ODBC Driver已淘汰
.NET Framework 2.0+ (VS 2005+)OLE DB .NET Provider (System.Data.OleDb)Microsoft OLE DB Provider for DB2 (Host Integration Server 組件)傳統維護模式
.NET Core / .NET 5+ (現代)ADO.NET Core (System.Data.Common)IBM Data Server Provider (NetProvider) — IBM.Data.DB2.Core NuGet推薦首選
.NET Core / .NET 5+Entity Framework CoreIBM.EntityFrameworkCore NuGetORM 首選

⚠️ 重要提示:本文重寫聚焦現代 .NET 6+ / .NET 8 環境下使用 IBM 官方 NetProvider (IBM.Data.DB2.Core) 的最佳實踐。原文基於 VS.NET Beta 2 / HIS 2000 的 OLE DB 方案已過時,僅供歷史維護參考。新項目請直接使用 IBM.Data.DB2.Core。

現代方案:IBM.Data.DB2.Core (NetProvider) 完整實戰

1. NuGet 依賴安裝


# Package Manager Console
Install-Package IBM.Data.DB2.Core -Version 7.0.0.100  # 或最新穩定版
Install-Package IBM.Data.DB2.Core-lnx  # Linux 運行時依賴 (自動包含)

# 或 .NET CLI
dotnet add package IBM.Data.DB2.Core

2. 連接字符串標準化


// appsettings.json
{
  "ConnectionStrings": {
    "DB2Connection": "Server=192.168.1.100:50000;Database=SAMPLE;UID=db2inst1;PWD=StrongPass123!;Connection Timeout=30;Pooling=true;Min Pool Size=5;Max Pool Size=100;Certificate=SSL_CERT_PATH;SSL=Required;"
  }
}

// 關鍵參數解析:
// Server=host:port (IPv6 用 [::1]:50000)
// Database=目標數據庫別名
// UID/PWD=認證
// Pooling=true (默認啟用,生產必開)
// Min/Max Pool Size=連接池邊界
// SSL=Required/Preferred/None (生產建議 Required)
// Certificate=客戶端證書路徑 (雙向 SSL)

3. DbContext / DbConnection 使用模式


// 模式 A: 純 ADO.NET (高性能、精細控制)
using IBM.Data.DB2.Core;
using (var conn = new DB2Connection(connectionString))
{
    await conn.OpenAsync();
    using (var cmd = conn.CreateCommand())
    {
        cmd.CommandText = "SELECT EMPNO, FIRSTNME, LASTNAME, SALARY FROM HR.EMPLOYEE WHERE WORKDEPT = @dept";
        cmd.Parameters.Add(new DB2Parameter("@dept", DB2Type.Char, 3) { Value = "A00" });
        
        using (var reader = await cmd.ExecuteReaderAsync())
        {
            while (await reader.ReadAsync())
            {
                Console.WriteLine($"{reader.GetString(0)} {reader.GetString(1)} {reader.GetString(2)} ${reader.GetDecimal(3)}");
            }
        }
    }
}

// 模式 B: Dapper 微型 ORM (推薦輕量級)
using Dapper;
using (var conn = new DB2Connection(connectionString))
{
    var employees = await conn.QueryAsync(
        "SELECT EMPNO, FIRSTNME, LASTNAME, SALARY FROM HR.EMPLOYEE WHERE WORKDEPT = @dept",
        new { dept = "A00" });
}

// 模式 C: Entity Framework Core (領域模型、變更追蹤)
public class SampleContext : DbContext
{
    public DbSet Employees { get; set; }
    public DbSet Departments { get; set; }
    
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseDB2(connectionString); // 需 IBM.EntityFrameworkCore
    }
    
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity(e => {
            e.ToTable("EMPLOYEE", "HR");
            e.HasKey(x => x.Empno);
            e.Property(x => x.Empno).HasColumnName("EMPNO").HasMaxLength(6).IsFixedLength();
            e.Property(x => x.FirstName).HasColumnName("FIRSTNME").HasMaxLength(12);
            // ... 其他映射
        });
    }
}

// 使用
using (var ctx = new SampleContext())
{
    var emps = await ctx.Employees.Where(e => e.WorkDept == "A00").ToListAsync();
}

4. 參數化查詢與類型映射最佳實踐

DB2 類型.NET 類型DB2Parameter 類型注意事項
CHAR(n)stringDB2Type.Char固定長度,需 PadRight(n) 或讀取時 TrimEnd()
VARCHAR(n)stringDB2Type.VarChar推薦新表使用
GRAPHIC/VARGRAPHICstringDB2Type.Graphic / VarGraphic雙字節字符集
SMALLINTshort / Int16DB2Type.SmallInt
INTEGERint / Int32DB2Type.Integer
BIGINTlong / Int64DB2Type.BigInt
DECIMAL(p,s)decimalDB2Type.DecimalPrecision/Scale 需匹配
REALfloat / SingleDB2Type.Real
DOUBLEdoubleDB2Type.Double
DATEDateTime / DateOnlyDB2Type.DateDateOnly (.NET 6+) 更語義化
TIMETimeSpan / TimeOnlyDB2Type.TimeTimeOnly (.NET 6+) 推薦
TIMESTAMPDateTimeDB2Type.Timestamp含微秒精度
BLOB/CLOBbyte[] / stringDB2Type.Blob / Clob大對象建議流式讀寫
XMLstring / XmlDocumentDB2Type.Xml需 XML 列許可

5. 大對象 (LOB) 流式處理


// 讀取 BLOB (照片) - 流式避免大內存
using (var conn = new DB2Connection(connStr))
{
    await conn.OpenAsync();
    using (var cmd = conn.CreateCommand())
    {
        cmd.CommandText = "SELECT PHOTO FROM HR.EMP_PHOTO WHERE EMPNO = @empno";
        cmd.Parameters.Add(new DB2Parameter("@empno", DB2Type.Char, 6) { Value = "000010" });
        
        using (var reader = await cmd.ExecuteReaderAsync(CommandBehavior.SequentialAccess))
        {
            if (await reader.ReadAsync())
            {
                using (var stream = reader.GetStream(0)) // DB2DataReader.GetStream
                using (var fileStream = File.Create("photo.jpg"))
                {
                    await stream.CopyToAsync(fileStream); // 直接寫入文件,不經內存緩衝
                }
            }
        }
    }
}

// 寫入 BLOB - 參數綁定大對象
using (var cmd = conn.CreateCommand())
{
    cmd.CommandText = "INSERT INTO HR.EMP_PHOTO (EMPNO, PHOTO_FORMAT, PHOTO) VALUES (@empno, @fmt, @photo)";
    cmd.Parameters.Add(new DB2Parameter("@empno", DB2Type.Char, 6) { Value = "000010" });
    cmd.Parameters.Add(new DB2Parameter("@fmt", DB2Type.VarChar, 10) { Value = "JPEG" });
    
    var photoParam = new DB2Parameter("@photo", DB2Type.Blob) { 
        Value = File.ReadAllBytes("photo.jpg") // 小文件可直接 byte[]
        // 大文件: 使用 DB2Parameter.Value = File.OpenRead("large_photo.jpg") 配合 SequentialAccess
    };
    cmd.Parameters.Add(photoParam);
    await cmd.ExecuteNonQueryAsync();
}

6. 事務管理與隔離級別


// 顯式事務 (ADO.NET)
using (var conn = new DB2Connection(connStr))
{
    await conn.OpenAsync();
    using (var tx = await conn.BeginTransactionAsync(IsolationLevel.ReadCommitted)) // DB2 默認 CS
    {
        try 
        {
            // ... 多條 DML
            await tx.CommitAsync();
        }
        catch
        {
            await tx.RollbackAsync();
            throw;
        }
    }
}

// EF Core 事務
using (var ctx = new SampleContext())
{
    using (var tx = await ctx.Database.BeginTransactionAsync(IsolationLevel.ReadCommitted))
    {
        try 
        {
            // ... 實體操作
            await ctx.SaveChangesAsync();
            await tx.CommitAsync();
        }
        catch
        {
            await tx.RollbackAsync();
            throw;
        }
    }
}

歷史方案參考:OLE DB Provider (僅維護舊系統用)

前置條件:Microsoft Host Integration Server (HIS) 2016/2020

  • HIS 安裝介質中包含 Microsoft OLE DB Provider for DB2
  • 安裝時選擇 Data Integration 角色
  • 提供 DB2OLEDB Provider (32/64 位均需)

連接字符串 (OLE DB)


Provider=DB2OLEDB;Data Source=QCDB;Network Transport Library=TCPIP;
Host CCSID=37;PC Code Page=1252;Network Address=192.168.1.100;Network Port=50000;
Package Collection=QCDB;Default Schema=USERID;User ID=userid;Password=pass;
Initial Catalog=QCDB;Persist Security Info=True;

C# 代碼 (System.Data.OleDb)


using System.Data.OleDb;
using (var conn = new OleDbConnection(oleDbConnStr))
{
    await conn.OpenAsync();
    using (var cmd = new OleDbCommand("SELECT * FROM ADDRESS", conn))
    using (var adapter = new OleDbDataAdapter(cmd))
    {
        var dt = new DataTable();
        adapter.Fill(dt); // 填充 DataTable
        // 數據綁定到 GridView 等
    }
}

性能優化與連接池調優

優化點配置/代碼效果
連接池預熱啟動時創建 MinPoolSize 個連接首請求零延遲
批量操作DB2Command.ArrayBindCount + Parameter.Value = ArrayINSERT/UPDATE 吞吐提升 10-50x
預取行數DB2Command.RowSize / FetchSize 調大 (如 1000)減少網絡往返
只讀查詢CommandBehavior.SequentialAccess + 單次讀取大結果集流式處理
準備語句緩存DB2 自動包緩存 + 應用層重用 Command編譯開銷歸零
異步管道await OpenAsync/ExecuteReaderAsync/ExecuteNonQueryAsync釋放執行緒、提升併發

常見問題排查

🔧 典型錯誤與解決

  • SQL30081N (通信錯誤):檢查防火牆、端口、HOSTNAME/IP、DB2COMM=TCPIP、svcename 配置
  • SQL1042C / SQL30082N (授權/認證失敗):UID/PWD 錯誤、用戶被鎖定、AUTHENTICATION 不匹配 (SERVER vs SERVER_ENCRYPT vs DATA_ENCRYPT)
  • SQL0805N (包未找到):靜態 SQL 需 BIND,動態 SQL 需 BINDADD 權限,運行 db2bind 或授權
  • SQL0901N/0902C (系統錯誤):查看 db2diag.log,常見於 LOB 內存不足、臨時表空間滿、代理進程崩潰
  • 中文亂碼:確保 CCSID/Code Page 一致 (DB: 1386/GBK, Client: 1252/UTF-8),連接字符串指定 CurrentSchema 避免隱式解析
  • .NET Core Linux 部署:需安裝 IBM.Data.DB2.Core-lnx 運行時依賴,Dockerfile 中 RUN apt-get install -y libxml2 libaio1

遷移建議:從 OLE DB 到 NetProvider

  1. 將 System.Data.OleDb 替換為 IBM.Data.DB2.Core
  2. 連接字符串簡化為關鍵字格式 (Server/Database/UID/PWD/SSL)
  3. 參數類型從 OleDbType 映射到 DB2Type
  4. 利用 DB2Command.ArrayBindCount 實現高性能批量操作
  5. 引入 Dapper/EF Core 簡化數據訪問層
  6. 配置 SSL 加密傳輸 (生產環境必備)

總結

現代 .NET 連接 DB2 的標準路徑:IBM.Data.DB2.Core (NuGet) + 關鍵字連接字符串 + 參數化查詢 + 異步模式 + Dapper/EF Core。放棄過時的 HIS/OLE DB 架構,擁抱跨平台、高性能、雲原生的 NetProvider。核心優勢:

  • 無額外中間件 (HIS),單一 NuGet 依賴
  • 原生 .NET Core/.NET 5+ 支持,Linux/Windows/macOS 同樣運行
  • Array Binding、流式 LOB、異步管道等高性能特性
  • 活躍維護,同步 DB2 新特性 (JSON、XML、向量、時間旅行)
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved