LotusAPI.Data 프레임워크용 PostgreSQL 어댑터 — NuGet 없이, DLL 참조만으로 바로 사용 가능
LotusAPI.Data의 SqliteDatabase, SqlExpressDatabase와 동일한 패턴으로 만들어진 PostgreSQL 백엔드입니다. DLL만 참조하면 바로 사용할 수 있습니다.
모든 DLL이 C:\LotusAPI\bin\에 있습니다. HintPath로 참조하면 끝.
EnsureTable()이 테이블을 자동 생성하고, 새 컬럼이 추가되면 자동으로 ALTER TABLE을 실행합니다.
SQLite/MySQL과 동시에 동작합니다. 기존 코드를 전혀 건드리지 않고 PostgreSQL을 추가할 수 있습니다.
LotusAPI.Data.Database를 상속. 기존 Table, Row, Column API를 그대로 사용합니다.
아래 파일들은 이미 bin 폴더에 있습니다. 따로 다운로드할 필요 없습니다.
| 파일명 | 버전 | 역할 |
|---|---|---|
| ATMC.Database.PostgreSQL.dll | — | 직접 제작 |
| Npgsql.dll | 5.0.18 | PostgreSQL 드라이버 |
| Microsoft.Bcl.AsyncInterfaces.dll | 5.0.0 | Npgsql 의존성 |
| Microsoft.Extensions.Logging.Abstractions.dll | 5.0.0 | Npgsql 의존성 |
| System.Diagnostics.DiagnosticSource.dll | 5.0.0 | Npgsql 의존성 |
| System.Text.Json.dll | 5.0.0.2 | Npgsql 의존성 |
| System.Runtime.CompilerServices.Unsafe.dll | 5.0.0 | Npgsql 의존성 |
| System.Memory.dll | 4.0.1.1 | Npgsql 의존성 |
| System.Buffers.dll | 4.0.3 | Npgsql 의존성 |
| System.Threading.Tasks.Extensions.dll | 4.2.0.1 | Npgsql 의존성 |
모든 프로젝트에서 동일하게 적용됩니다. 복사-붙여넣기만 하면 됩니다.
프로젝트 파일의 <ItemGroup> 안에 아래 두 줄을 추가합니다.
<!-- PostgreSQL 라이브러리 참조 --> <Reference Include="ATMC.Database.PostgreSQL"> <HintPath>C:\LotusAPI\bin\ATMC.Database.PostgreSQL.dll</HintPath> </Reference> <Reference Include="Npgsql"> <HintPath>C:\LotusAPI\bin\Npgsql.dll</HintPath> </Reference>
Npgsql의 의존 DLL 버전이 맞지 않아 발생하는 오류를 막기 위해 App.config에 아래 블록 전체를 붙여넣습니다.
<runtime> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> <assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/> <bindingRedirect oldVersion="0.0.0.0-5.0.0.0" newVersion="5.0.0.0"/> </dependentAssembly> <dependentAssembly> <assemblyIdentity name="Microsoft.Bcl.AsyncInterfaces" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral"/> <bindingRedirect oldVersion="0.0.0.0-5.0.0.0" newVersion="5.0.0.0"/> </dependentAssembly> <dependentAssembly> <assemblyIdentity name="System.Text.Json" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral"/> <bindingRedirect oldVersion="0.0.0.0-5.0.0.2" newVersion="5.0.0.2"/> </dependentAssembly> <dependentAssembly> <assemblyIdentity name="Microsoft.Extensions.Logging.Abstractions" publicKeyToken="adb9793829ddae60" culture="neutral"/> <bindingRedirect oldVersion="0.0.0.0-5.0.0.0" newVersion="5.0.0.0"/> </dependentAssembly> <dependentAssembly> <assemblyIdentity name="System.Diagnostics.DiagnosticSource" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral"/> <bindingRedirect oldVersion="0.0.0.0-5.0.0.0" newVersion="5.0.0.0"/> </dependentAssembly> <dependentAssembly> <assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral"/> <bindingRedirect oldVersion="0.0.0.0-4.0.1.1" newVersion="4.0.1.1"/> </dependentAssembly> <dependentAssembly> <assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral"/> <bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0"/> </dependentAssembly> <dependentAssembly> <assemblyIdentity name="System.Threading.Tasks.Extensions" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral"/> <bindingRedirect oldVersion="0.0.0.0-4.2.0.1" newVersion="4.2.0.1"/> </dependentAssembly> </assemblyBinding> </runtime>
설정 UI에서 PostgreSQL 접속 정보를 변경할 수 있도록 아래 속성들을 추가합니다.
// MySetting 클래스 안에 추가 public Property_<string> DBServerAddress { get; } = new Property_<string>("localhost", "DB", WriteProtectionType.AskForPermission); public Property_<int> DBServerPort { get; } = new Property_<int>(5432, "DB", WriteProtectionType.AskForPermission); public Property_<string> DBName { get; } = new Property_<string>("atmc", "DB", WriteProtectionType.AskForPermission); public Property_<string> DBUser { get; } = new Property_<string>("postgres", "DB", WriteProtectionType.AskForPermission); public Property_<string> DBPassword { get; } = new Property_<string>("", "DB", WriteProtectionType.AskForPermission);
기존 SQLite DB/InitDB()는 절대 건드리지 않습니다. 아래 코드를 추가만 합니다. EnsureTable()은 SQLite의 Table 객체를 빼앗지 않고 PostgreSQL에만 테이블을 생성합니다.
// 상단에 추가 using ATMC.Database.PostgreSQL; // DATABASE 리전 안에 추가 (기존 DB/InitDB는 그대로) public static PostgreSqlDatabase PgDB = null; public static void InitPgDB() { try { PgDB = new PostgreSqlDatabase( Setting.DBServerAddress, Setting.DBServerPort, Setting.DBName, Setting.DBUser, Setting.DBPassword); if (PgDB.Connect()) PgDB.EnsureTable(DB.MyTable); // 테이블 자동 생성 (SQLite Table 영향 없음) } catch (Exception ex) { Logger.Error(ex.Message); } } // Init() 에서 InitDB() 바로 다음에 호출 public static void Init() { InitDB(); InitPgDB(); // ← 이 한 줄 추가 // 나머지는 그대로 }
SQLite 삽입 코드 바로 다음에 한 줄만 추가합니다. ?. 연산자를 사용하므로 PgDB가 null이면 자동으로 건너뜁니다.
// 기존 SQLite 삽입 — 건드리지 않음 DB.MyTable.InsertRow(row); // 바로 아래에 이 한 줄 추가 Global.PgDB?.InsertRow(row);
result, date, model 등). 이는 PostgreSQL 표준 규칙이며 라이브러리가 자동으로 처리합니다.
파일 위치 한눈에 보기
공개(public) 메서드 전체 목록과 동작 방식
호스트, 포트, DB명, 사용자명, 비밀번호를 받아 Npgsql 연결 문자열을 자동으로 조합합니다.
내부적으로 Host=...;Port=...;Database=...;Username=...;Password=...; 형식으로 변환됩니다.
var pgDB = new PostgreSqlDatabase("localhost", 5432, "atmc", "postgres", "1234");
Npgsql 연결 문자열을 직접 전달하는 오버로드입니다.
var pgDB = new PostgreSqlDatabase("Host=localhost;Port=5432;Database=atmc;Username=postgres;Password=1234;");
PostgreSQL 서버에 실제로 연결을 시도합니다. 성공하면 true, 실패하면 false를 반환하고 오류를 로그에 기록합니다.
연결 실패 시 내부 예외(InnerException)까지 모두 로그에 출력하여 원인 파악을 쉽게 합니다.
if (pgDB.Connect()) { // 연결 성공 }
PostgreSQL에 테이블이 없으면 자동 생성하고, 컬럼이 추가된 경우 ALTER TABLE ... ADD COLUMN으로 자동 마이그레이션합니다.
AddTable()과의 차이: EnsureTable()은 Table 객체를 이 DB에 등록하지 않습니다. 따라서 SQLite DB가 사용 중인 Table 객체를 공유해도 SQLite 동작에 전혀 영향을 주지 않습니다.
if (pgDB.Connect()) pgDB.EnsureTable(DB.MyTable); // SQLite MyTable을 PostgreSQL에도 생성
LotusAPI의 Row 객체를 PostgreSQL에 삽입합니다. Primary Key 컬럼(SERIAL)은 자동으로 건너뜁니다.
성공 시 로그에 기록하고 true 반환. 실패 시 전체 예외 체인을 로그에 출력하고 false 반환.
// SQLite 삽입 후 바로 PostgreSQL에도 삽입 DB.MyTable.InsertRow(row); Global.PgDB?.InsertRow(row); // PgDB가 null이면 자동 스킵
LotusAPI.Data.Database의 AddTable()을 재정의합니다. 테이블을 이 DB에 완전히 등록하고, 없는 컬럼은 자동 추가합니다.
PgDB가 Table을 단독으로 소유할 때(SQLite와 공유하지 않을 때)만 사용하세요. 공유 시에는 EnsureTable()을 사용합니다.
SELECT 쿼리를 PostgreSQL 문법으로 생성합니다. LotusAPI.Data.CommonQuery 내부에서 자동으로 사용됩니다.
SELECT 절을 생성합니다. 컬럼명은 PostgreSQL 이중 따옴표 스타일("column")로 자동 처리됩니다.
SELECT "DATE", "MODEL", "RESULT" -- Select() SELECT * -- SelectAll() SELECT DISTINCT "MODEL" -- SelectDistinct()
집계 함수를 생성합니다.
SELECT COUNT(*) -- Count() SELECT AVG("FIT") -- Average("FIT") SELECT SUM("OVL") -- Sum("OVL")
날짜 컬럼에서 특정 부분을 추출하는 PostgreSQL EXTRACT() 표현식을 반환합니다.
EXTRACT(DAY FROM "DATE")::INTEGER -- Day("DATE") EXTRACT(MONTH FROM "DATE")::INTEGER -- Month("DATE") EXTRACT(YEAR FROM "DATE")::INTEGER -- Year("DATE")
날짜를 월 이름 또는 요일 이름 문자열로 변환하는 TO_CHAR() 표현식을 반환합니다.
TO_CHAR("DATE", 'Mon') -- MonthName() → "Jan", "Feb"...
TO_CHAR("DATE", 'Dy') -- WeekDayName() → "Mon", "Tue"...
PostgreSQL의 LIMIT / OFFSET 페이지네이션을 생성합니다.
ORDER BY "DATE" DESC LIMIT 100 OFFSET 50
WHERE 조건을 PostgreSQL 이중 따옴표 스타일로 생성합니다.
| 메서드 | 생성되는 SQL |
|---|---|
| Equal("RESULT", "OK") | ("RESULT" = 'OK') |
| NotEqual("RESULT", "NG") | ("RESULT" <> 'NG') |
| Like("MODEL", "A%") | ("MODEL" LIKE 'A%') |
| Between("DATE", d1, d2) | ("DATE" BETWEEN 'd1' AND 'd2') |
| LessThan("FIT", 0.5) | ("FIT" < '0.5') |
| MoreThanOrEqual("OVL", 0.8) | ("OVL" >= '0.8') |
| In("MODEL", "A", "B", "C") | ("MODEL" IN ('A', 'B', 'C')) |
| Not("조건") | (NOT 조건) |
GetTypeStr()이 자동으로 변환합니다.