甚麼是 ODBC,維基百科這樣說
"ODBC(Open Database Connectivity,開放資料庫互連)提供了一種標準的 API( 應用程式編程介面)方法來訪問資料庫管理系統(DBMS)。ODBC 的運用形態通常是由應用程式經過一個稱之為 ODBC 管理器的工具,建立一個 DSN,指明需要呼叫的 ODBC 驅動程式,從而訪問對應的資料庫。"
簡單來說,可以透過 ODBC 來簡化連線字串的管理,最近工作上,需要用到它,趕緊趁無風無雨的颱風天,重新學習一下。
ODBC - 維基百科,自由的百科全書 (wikipedia.org)
開發環境
- Windows 11 Home
- .NET 8
- Rider 2024.2
- PostgreSQL 12
連線字串
PostgreSQL connection strings - ConnectionStrings.com
安裝
在作業系統安裝 PostgreSQL ODBC Driver,下載位置為 psqlodbc - PostgreSQL ODBC driver
測試環境
這裡我要用 EF Core + TestContainer 建立環境以及測試資料,開一個測試專案,安裝以下套件
dotnet add package Testcontainers.PostgreSql --version 3.10.0
dotnet add package Npgsql.EntityFrameworkCore.PostgreSQL --version 8.0.8
在測試專案一起動的時候就建立 PostgreSqlContainer 並呼叫 InsertTestData 新增測試資料
[TestClass]
public static class Initialize
{
static IContainer? PostgreSqlContainer;
[AssemblyInitialize]
public static void AssemblyInitialize(TestContext context)
{
Console.WriteLine("AssemblyInitialize");
PostgreSqlContainer = CreatePostgreSQLContainer();
PostgreSqlContainer.StartAsync().GetAwaiter().GetResult();
InsertTestData();
}
private static void InsertTestData()
{
var connectionString = "Host=localhost;Port=5432;Database=employee;Username=postgres;Password=postgres";
var dbContextOptions = new DbContextOptionsBuilder<EmployeeDbContext>()
.UseNpgsql(connectionString)
.Options;
using var dbContext = new EmployeeDbContext(dbContextOptions);
dbContext.Database.EnsureCreated();
dbContext.Employees.Add(new Employee
{
Id = Guid.NewGuid(),
Name = "yao",
Age = 18,
Remark = null,
CreateAt = DateTime.UtcNow,
CreateBy = "yao"
});
dbContext.SaveChanges();
}
[AssemblyCleanup]
public static void AssemblyCleanup()
{
Console.WriteLine("AssemblyCleanup");
PostgreSqlContainer.StopAsync().GetAwaiter().GetResult();
PostgreSqlContainer.DisposeAsync().GetAwaiter().GetResult();
}
private static IContainer CreatePostgreSQLContainer()
{
var waitStrategy = Wait.ForUnixContainer().UntilCommandIsCompleted("pg_isready");
var container = new ContainerBuilder()
.WithImage("postgres:12-alpine")
.WithName("postgres.12")
.WithPortBinding(5432)
.WithWaitStrategy(waitStrategy)
.WithEnvironment("POSTGRES_USER", "postgres")
.WithEnvironment("POSTGRES_PASSWORD", "postgres")
.WithEnvironment("POSTGRES_DB", "employee")
.Build();
return container;
}
}
使用 ADO.NET OdbcConnection 訪問資料庫
在專案安裝 ODBC 套件
dotnet add package System.Data.Odbc --version 8.0.0
用 ADO.NET 讀取資料
[TestMethod]
public async Task ReadForAdoNet()
{
var connectionString =
"Driver={PostgreSQL Unicode};Server=localhost;Port=5432;Database=employee;Uid=postgres;Pwd=postgres;";
await using var connection = new OdbcConnection(connectionString);
await using var command = new OdbcCommand();
await connection.OpenAsync();
command.Connection = connection;
command.CommandText = @"select * from ""Employee""";
await using var reader = await command.ExecuteReaderAsync();
while (true)
{
var hasData = await reader.ReadAsync();
if (hasData == false)
{
break;
}
for (var i = 0; i < reader.FieldCount; i++)
{
var name = reader.GetName(i);
var value = reader.GetValue(i);
Console.WriteLine($"{name}: {value}");
}
}
await connection.CloseAsync();
}
搭配 Dapper 做 Model Mapping
安裝套件
dotnet add package Dapper --version 2.1.35
[TestMethod]
public async Task ReadForDapper()
{
var connectionString =
"Driver={PostgreSQL Unicode};Server=localhost;Port=5432;Database=employee;Uid=postgres;Pwd=postgres;";
await using var connection = new OdbcConnection(connectionString);
var sql = @"select * from ""Employee""";
var data = connection.Query<Employee>(sql).ToList();
await connection.CloseAsync();
}
用 DSN 連接 PostgreSQL
ODBC 只需要提供 DSN 名稱,而非完整的連接字串,就能訪問資料庫,首先要先配置 ODBC,Win+S 搜尋 ODBC
名稱就是 DSN,等下連線字串改用這個名稱
範例程式如下,用 DSN 就能訪問資料庫了
[TestMethod]
public async Task ReadForDsn()
{
var dsn = "PostgreSQL";
var connectionString = $"DSN={dsn}";
await using var connection = new OdbcConnection(connectionString);
var sql = @"select * from ""Employee""";
var data = connection.Query<Employee>(sql).ToList();
await connection.CloseAsync();
}
心得
ODBC DSN 的確可以簡化管理者的維護工作,多墊了一層 ODBC Driver,唯一要注意的應該就是效能議題了吧,下圖是問 AI 得到的結果
下面這個連結則是別人寫的性能比較
SSIS 数据流性能比较 (ADO.NET vs. OLE DB vs. ODBC) - larryqian86 - 博客园 (cnblogs.com)
另外,EF Core 預設也沒有支援 ODBC,QQ
範例位置
若有謬誤,煩請告知,新手發帖請多包涵
Microsoft MVP Award 2010~2017 C# 第四季
Microsoft MVP Award 2018~2022 .NET