Library Documentation

ATMC.Database.PostgreSQL

LotusAPI.Data 프레임워크용 PostgreSQL 어댑터 — NuGet 없이, DLL 참조만으로 바로 사용 가능

● .NET Framework 4.8
● Npgsql 5.0.18
● NuGet 불필요
● 자동 스키마 마이그레이션

이 라이브러리는 무엇인가요?

LotusAPI.Data의 SqliteDatabase, SqlExpressDatabase와 동일한 패턴으로 만들어진 PostgreSQL 백엔드입니다. DLL만 참조하면 바로 사용할 수 있습니다.

🔌

NuGet 불필요

모든 DLL이 C:\LotusAPI\bin\에 있습니다. HintPath로 참조하면 끝.

🗄️

자동 테이블 생성

EnsureTable()이 테이블을 자동 생성하고, 새 컬럼이 추가되면 자동으로 ALTER TABLE을 실행합니다.

듀얼 쓰기

SQLite/MySQL과 동시에 동작합니다. 기존 코드를 전혀 건드리지 않고 PostgreSQL을 추가할 수 있습니다.

🔧

LotusAPI 네이티브

LotusAPI.Data.Database를 상속. 기존 Table, Row, Column API를 그대로 사용합니다.

C:\LotusAPI\bin\ 에 있어야 할 DLL 목록

아래 파일들은 이미 bin 폴더에 있습니다. 따로 다운로드할 필요 없습니다.

파일명버전역할
ATMC.Database.PostgreSQL.dll직접 제작
Npgsql.dll5.0.18PostgreSQL 드라이버
Microsoft.Bcl.AsyncInterfaces.dll5.0.0Npgsql 의존성
Microsoft.Extensions.Logging.Abstractions.dll5.0.0Npgsql 의존성
System.Diagnostics.DiagnosticSource.dll5.0.0Npgsql 의존성
System.Text.Json.dll5.0.0.2Npgsql 의존성
System.Runtime.CompilerServices.Unsafe.dll5.0.0Npgsql 의존성
System.Memory.dll4.0.1.1Npgsql 의존성
System.Buffers.dll4.0.3Npgsql 의존성
System.Threading.Tasks.Extensions.dll4.2.0.1Npgsql 의존성

새 프로젝트에 추가하는 방법 (5단계)

모든 프로젝트에서 동일하게 적용됩니다. 복사-붙여넣기만 하면 됩니다.

1

.csproj에 DLL 참조 추가

프로젝트 파일의 <ItemGroup> 안에 아래 두 줄을 추가합니다.

XMLYourProject.csproj
<!-- 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>
2

App.config에 바인딩 리다이렉트 추가

Npgsql의 의존 DLL 버전이 맞지 않아 발생하는 오류를 막기 위해 App.config에 아래 블록 전체를 붙여넣습니다.

XMLApp.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>
3

MySetting.cs에 DB 설정 추가

설정 UI에서 PostgreSQL 접속 정보를 변경할 수 있도록 아래 속성들을 추가합니다.

C#MySetting.cs
// 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);
4

Global.cs에 PgDB 추가

기존 SQLite DB/InitDB()는 절대 건드리지 않습니다. 아래 코드를 추가만 합니다. EnsureTable()은 SQLite의 Table 객체를 빼앗지 않고 PostgreSQL에만 테이블을 생성합니다.

C#Global.cs
// 상단에 추가
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(); // ← 이 한 줄 추가
    // 나머지는 그대로
}
5

SaveDB()에 PostgreSQL 삽입 추가

SQLite 삽입 코드 바로 다음에 한 줄만 추가합니다. ?. 연산자를 사용하므로 PgDB가 null이면 자동으로 건너뜁니다.

C#Result.cs — SaveDB()
// 기존 SQLite 삽입 — 건드리지 않음
DB.MyTable.InsertRow(row);

// 바로 아래에 이 한 줄 추가
Global.PgDB?.InsertRow(row);
참고: PostgreSQL에서 테이블명과 컬럼명은 소문자로 저장됩니다 (result, date, model 등). 이는 PostgreSQL 표준 규칙이며 라이브러리가 자동으로 처리합니다.

어디에 무엇을 넣는가

파일 위치 한눈에 보기

C:\LotusAPI\bin\  ← 모든 DLL의 집결지
  ├── ATMC.Database.PostgreSQL.dll  ← 이 라이브러리
  ├── Npgsql.dll  ← PostgreSQL 드라이버
  ├── Microsoft.Bcl.AsyncInterfaces.dll
  ├── Microsoft.Extensions.Logging.Abstractions.dll
  ├── System.Diagnostics.DiagnosticSource.dll
  ├── System.Text.Json.dll
  ├── System.Runtime.CompilerServices.Unsafe.dll
  ├── System.Memory.dll, System.Buffers.dll, System.Threading.Tasks.Extensions.dll
  └── LotusAPI.Data.dll  ← InternalsVisibleTo 패치 적용됨

YourProject\
  ├── YourProject.csproj  ← HintPath 참조 추가 (Step 1)
  ├── App.config  ← 바인딩 리다이렉트 추가 (Step 2)
  ├── MySetting.cs  ← DB 속성 추가 (Step 3)
  ├── Global.cs  ← PgDB + InitPgDB 추가 (Step 4)
  └── Result.cs  ← PgDB?.InsertRow(row) 추가 (Step 5)

PostgreSqlDatabase — 메서드 설명

공개(public) 메서드 전체 목록과 동작 방식

PostgreSqlDatabase(string host, int port, string database, string username, string password)
생성자

호스트, 포트, DB명, 사용자명, 비밀번호를 받아 Npgsql 연결 문자열을 자동으로 조합합니다.

내부적으로 Host=...;Port=...;Database=...;Username=...;Password=...; 형식으로 변환됩니다.

var pgDB = new PostgreSqlDatabase("localhost", 5432, "atmc", "postgres", "1234");
PostgreSqlDatabase(string connectionString)
생성자

Npgsql 연결 문자열을 직접 전달하는 오버로드입니다.

var pgDB = new PostgreSqlDatabase("Host=localhost;Port=5432;Database=atmc;Username=postgres;Password=1234;");
bool Connect()
bool

PostgreSQL 서버에 실제로 연결을 시도합니다. 성공하면 true, 실패하면 false를 반환하고 오류를 로그에 기록합니다.

연결 실패 시 내부 예외(InnerException)까지 모두 로그에 출력하여 원인 파악을 쉽게 합니다.

if (pgDB.Connect()) {
    // 연결 성공
}
void EnsureTable(Table table)
void

PostgreSQL에 테이블이 없으면 자동 생성하고, 컬럼이 추가된 경우 ALTER TABLE ... ADD COLUMN으로 자동 마이그레이션합니다.

AddTable()과의 차이: EnsureTable()은 Table 객체를 이 DB에 등록하지 않습니다. 따라서 SQLite DB가 사용 중인 Table 객체를 공유해도 SQLite 동작에 전혀 영향을 주지 않습니다.

SQLite DB와 Table 객체를 공유할 때는 반드시 EnsureTable()을 사용하세요. AddTable()을 사용하면 Table의 소유권이 PgDB로 넘어가 SQLite 삽입이 실패합니다.
if (pgDB.Connect())
    pgDB.EnsureTable(DB.MyTable); // SQLite MyTable을 PostgreSQL에도 생성
bool InsertRow(Row row)
bool

LotusAPI의 Row 객체를 PostgreSQL에 삽입합니다. Primary Key 컬럼(SERIAL)은 자동으로 건너뜁니다.

성공 시 로그에 기록하고 true 반환. 실패 시 전체 예외 체인을 로그에 출력하고 false 반환.

// SQLite 삽입 후 바로 PostgreSQL에도 삽입
DB.MyTable.InsertRow(row);
Global.PgDB?.InsertRow(row); // PgDB가 null이면 자동 스킵
void AddTable(Table table)
void

LotusAPI.Data.Database의 AddTable()을 재정의합니다. 테이블을 이 DB에 완전히 등록하고, 없는 컬럼은 자동 추가합니다.

PgDB가 Table을 단독으로 소유할 때(SQLite와 공유하지 않을 때)만 사용하세요. 공유 시에는 EnsureTable()을 사용합니다.

PostgreSqlQueryBuilder — 쿼리 빌더

SELECT 쿼리를 PostgreSQL 문법으로 생성합니다. LotusAPI.Data.CommonQuery 내부에서 자동으로 사용됩니다.

Select / SelectAll / SelectDistinct
IQueryBuilder

SELECT 절을 생성합니다. 컬럼명은 PostgreSQL 이중 따옴표 스타일("column")로 자동 처리됩니다.

SELECT "DATE", "MODEL", "RESULT"   -- Select()
SELECT *                           -- SelectAll()
SELECT DISTINCT "MODEL"            -- SelectDistinct()
Count / Average / Sum / Min / Max
IQueryBuilder

집계 함수를 생성합니다.

SELECT COUNT(*)        -- Count()
SELECT AVG("FIT")     -- Average("FIT")
SELECT SUM("OVL")     -- Sum("OVL")
Day / Month / Year / Hour / Minute
string

날짜 컬럼에서 특정 부분을 추출하는 PostgreSQL EXTRACT() 표현식을 반환합니다.

EXTRACT(DAY   FROM "DATE")::INTEGER  -- Day("DATE")
EXTRACT(MONTH FROM "DATE")::INTEGER  -- Month("DATE")
EXTRACT(YEAR  FROM "DATE")::INTEGER  -- Year("DATE")
MonthName / WeekDayName
string

날짜를 월 이름 또는 요일 이름 문자열로 변환하는 TO_CHAR() 표현식을 반환합니다.

TO_CHAR("DATE", 'Mon')  -- MonthName() → "Jan", "Feb"...
TO_CHAR("DATE", 'Dy')   -- WeekDayName() → "Mon", "Tue"...
Limit(column, descending, offset, length)
IQueryBuilder

PostgreSQL의 LIMIT / OFFSET 페이지네이션을 생성합니다.

ORDER BY "DATE" DESC
LIMIT 100 OFFSET 50

PostgreSqlConditionBuilder — WHERE 조건 빌더

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 조건)

LotusAPI 컬럼 타입 → PostgreSQL 타입

GetTypeStr()이 자동으로 변환합니다.

IntColumn (PK)SERIAL PRIMARY KEY
IntColumnINTEGER
FloatColumnREAL
DoubleColumnDOUBLE PRECISION
CharColumn(n)CHAR(n)
DatetimeColumnTIMESTAMP
TextColumnTEXT
BoolColumnBOOLEAN