C# 32비트와 64비트를 모두 지원하는 SQLite 응용 프로그램 개발하기
다중 사용자 환경이 아닌 응용 프로그램의 데이터베이스로는 SQLite 만한 것이 없다. 윈도, 리눅스, 맥과 같은 범용 운영체제뿐만 아니라 안드로이드 등 수많은 환경에서 SQL 기반으로 프로그래밍을 할 수 있기 때문이다. 파일 시스템을 사용하는 소위 삽질을 하지 않더라도 SQL을 사용해서 가독성도 높이고 생산성과 유지보수 등에 있어 수많은 장점을 가진 프로그램을 개발할 수 있다.
SQLite를 사용하는 프로그램은 프로그램 배포 과정에서 문제가 발생할 수 있다. 개발 환경에서는 문제없이 잘 동작했는데 막상 실제 수행 환경으로 가면 종종 문제가 발생하는 것이다. 대부분의 문제를 살펴보면 그 원인은 라이브러리에 있는데 수행 환경의 32비트/64비트 환경과 일치하는 라이브러리가 배포되지 않았기 때문이다. 32비트용과 64비트용을 따로 배포하는 방법도 있겠으나 라이브러리 자체에서 32/64 비트 환경을 자동적으로 인식하여 처리하면 더 간편하게 처리할 수 있다.
해당 라이브러리는 비주얼 스튜디오 NuGet 도구를 통해서 프로젝트에 간편하게 포함시킬 수 있는데 도구에서 "SQLite"로 검색하면 상당히 많은 도구들이 검색되는데 그중에서 위의 그림과 같이 System.Data.SQLite.Core(x86/x64)를 선택해서 설치한다.
개발에 필요한 라이브러리 파일은 위의 그림과 같으므로 개발 및 배포 환경에 적절히 적용하면 된다. NuGet 도구를 사용하는데 문제가 있는 분들을 위해 아래에 파일을 첨부한다. 라이선스는 Public domain으로 사용 및 배포에 제한이 없다.
using System;
using System.Data;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Data.SQLite;
namespace hisbookcom
{
public class DBSQLite
{
private static String connstr = "Data Source=hisbook.db;Pooling=true;FailIfMissing=false";
private static SQLiteConnection conn = null;
public static String error_message = null;
public static bool open()
{
SQLiteCommand cmd;
if (conn != null) return true;
try
{
conn = new SQLiteConnection(connstr);
conn.Open();
//환경 테이블 검사 및 생성, 읽기
cmd = new SQLiteCommand("SELECT COUNT(*) cnt FROM sqlite_master WHERE name = 'pgmconfig'", conn);
int chkcnt = Convert.ToInt32(cmd.ExecuteScalar());
if (chkcnt <= 0) // table not exist -> create
{
cmd.CommandText = "CREATE TABLE pgmconfig (cfgname VARCHAR(16), cfgint INTEGER, cfgstr VARCHAR(370), PRIMARY KEY(cfgname));";
cmd.ExecuteNonQuery();
cmd.CommandText = "INSERT INTO pgmconfig (cfgname, cfgint) VALUES ('READ_BOOKLANG', 0);";
cmd.ExecuteNonQuery();
}
cmd.CommandText = "SELECT * FROM pgmconfig";
DataTable rettbl = getTable(cmd);
if (rettbl == null || rettbl.Rows.Count <= 0)
{
conn.Close();
error_message += " 환경 읽기 오류";
return false;
}
foreach (DataRow dr in rettbl.Rows)
{
if (Convert.IsDBNull(dr["cfgint"]))
Comgbl.Configstr[dr["cfgname"].ToString()] = dr["cfgstr"].ToString();
else
Comgbl.Configint[dr["cfgname"].ToString()] = Convert.ToInt32(dr["cfgint"]);
}
}
catch (SQLiteException ex)
{
error_message = "DB 초기화 실패 " + ex.Message;
if (conn != null)
{
conn.Close();
conn = null;
}
return false;
}
return true;
}
public static void close()
{
if (conn != null) conn.Close();
}
public static String escape_str(String instr)
{
return instr.Replace("'", "\\'");
}
public static DataRow get1Row(SQLiteCommand cmd)
{
SQLiteDataReader reader = null;
DataTable rsttbl = null;
try
{
reader = cmd.ExecuteReader();
if (!reader.HasRows)
{
reader.Close();
}
else
{
rsttbl = new DataTable();
rsttbl.Load(reader);
}
}
catch (Exception ex)
{
error_message = "DB 오류 " + ex.Message;
}
finally
{
if (reader != null) reader.Close();
}
if (rsttbl != null) return rsttbl.Rows[0];
return null;
}
public static DataTable getTable(SQLiteCommand cmd)
{
SQLiteDataReader reader = null;
DataTable rsttbl = null;
try
{
reader = cmd.ExecuteReader();
if (!reader.HasRows)
{
reader.Close();
}
else
{
rsttbl = new DataTable();
rsttbl.Load(reader);
}
}
catch (Exception ex)
{
error_message = "DB 오류 " + ex.Message;
}
finally
{
if (reader != null) reader.Close();
}
if (rsttbl != null) return rsttbl;
return null;
}
}
}
위의 코드는 DB 연결부터 테이블 존재 여부 검사와 테이블 생성, 데이터 삽입, 쿼리 등을 수행하는 예제이다.