C#으로 SQLite 다루기

메모리 기반에서 자료를 다루기 위해 Array나 Linked List 그리고 Hashmap 등을 사용하지만, 대용량 또는 SQL 문을 통한 다양한 조건검색을 위해 DBMS을 사용해야할 때가 있습니다. 설치도 필요없고 가볍고 빠르게 사용할 수 있는 Local DBMS로 SQLite는 안드로이드나 SVN 등과 같이 매우 광범위하게 사용되는데.. C#으로 이 SQLite를 다루는 내용에 대해 정리를 해 봅니다.

C#에서 SQLite를 사용하기 위해서는 먼저 .NET용 SQLite 어셈블리 모듈을 설치해야 합니다. SQLite 공식 사이트에서 관련 파일을 설치할 수 있는 setup 파일을 받아 설치하기 바랍니다.

개발을 위해 필요한 파일이 설치되면 Visual Studio에서 C# 프로젝트를 생성하고 아래의 화면처럼 어셈블리 참조를 추가해 줍니다.

위의 화면에서 추가한 System.Data.SQLite 참조는 SQLite를 위한 ADO.NET 데이터 제공자(Data Provider)입니다. 이 참조는 앞서 설치된 폴더에 System.Data.SQLite.dll 파일을 통해 추가할 수 있습니다.

참조를 추가했으므로 코드에서 참조와 관련된 클래스를 빠르게 접근하기 위한 아래의 using 문을 추가합니다.

using System.Data.SQLite;

이제 다음과 같은 폼을 디자인함으로써 SQLite에 대한 주요 내용에 대한 코드를 살펴 보겠습니다.

폼 상에 버튼의 제목을 통해 우리가 파악할 SQLite에 대한 코드가 무엇인지 짐작할 수 있습니다. 즉, 아래와 같습니다.

  1. Create DB File – SQLite DB 파일을 생성합니다.
  2. Open DB – 생성한 DB 파일을 사용하기 위해 연결합니다.
  3. Create Table – DB 파일에 테이블을 생성합니다.
  4. Insert Row – 생성한 테이블에 Row를 추가합니다.
  5. Query Data – 테이블에 저장된 데이터를 조회합니다.
  6. Close Connection – DB 파일에 대한 연결을 닫습니다.

먼저 SQLite DB 파일을 생성하는 버튼에 대한 코드는 다음과 같습니다.

SQLiteConnection.CreateFile("c:/a.sqlite");

위의 코드가 성공한다면 C:\ 경로에 a.sqlite라는 파일이 생성될 것입니다. 다음은 생성한 DB 파일을 사용하기 위해 연결하는 코드입니다.

conn = new SQLiteConnection("Data Source=c:/a.sqlite;Version=3;");
conn.Open();

위의 코드에서 conn 변수는 다음과 같이 정의되어 있습니다.

private SQLiteConnection conn = null;

이제 다음은 DB 파일에 테이블을 생성하는 코드입니다.

string sql = "create table members (name varchar(20), age int)";

SQLiteCommand command = new SQLiteCommand(sql, conn);
int result = command.ExecuteNonQuery();

sql = "create index idx01 on members(name)";
command = new SQLiteCommand(sql, conn);
result = command.ExecuteNonQuery();

우리가 흔히 알고 있는 CREATE SQL 문을 통해 테이블을 생성하고 있습니다. 추가적으로 인덱스(INDEX)까지도 생성하고 있습니다. 이제 다음은 생성한 테이블에 Row를 추가하는 코드입니다.

String sql = "insert into members (name, age) values ('김도현', 6)";

SQLiteCommand command = new SQLiteCommand(sql, conn);
int result = command.ExecuteNonQuery();

아.. 우리 와이프 코고는 소리가 들리네요.. -_-; 여튼.. 위의 코드를 보면 Row를 추가하기 위해 흔히 알고 있는 INSERT SQL문을 사용하고 있습니다. 다음은 테이블에 저장된 데이터에 대한 조회 코드입니다.

String sql = "select * from members";

SQLiteCommand cmd = new SQLiteCommand(sql, conn);
SQLiteDataReader rdr = cmd.ExecuteReader();
while (rdr.Read()) {
    MessageBox.Show(rdr["name"] + " " + rdr["age"]);
}

rdr.Close();

SELECT SQL문을 통해 조회할 수 있으며, SQLiteDataReader 클래스를 통해 실제 조회된 데이터를 필드별로 읽어 낼 수 있는 것을 볼 수 있습니다. 이제 끝으로 DB에 연결된 Connection 객체를 닫는 코드는 아래와 같습니다.

conn.Close();

자, 이상으로 요긴하게 바로 사용할 수 있는 Local DBMS인 SQLite를 C#에서 사용할 수 있는 최소한의 내용을 정리해 보았습니다.

[C#] 관리자 권한으로 실행하기

관리자 권한이 없는 상태에서 시스템의 정보를 읽거나 쓰려고 할때 프로그램이 올바르게 작동하지 않습니다. 이럴때 프로그램이 실행되면서, 관리자 권한으로 상승시키는 것이 필요한데요. C#에서 이러한 내용에 대한 코드를 정리합니다. 모든 코드는 Program.cs에서 이루어집니다. 먼저 using 절에 다음과 같은 네임스페이스를 추가합니다.

using System.Security.Principal;
using System.Diagnostics;

그리고 현재 관리자 권한 상태인지의 여부를 파악하는 함수를 추가합니다.

public static bool IsAdministrator()
{
    WindowsIdentity identity = WindowsIdentity.GetCurrent();

    if (null != identity)
    {
        WindowsPrincipal principal = new WindowsPrincipal(identity);
        return principal.IsInRole(WindowsBuiltInRole.Administrator);
    }

    return false;
}

Program.cs 파일의 Main 함수의 시작 부분에 다음의 코드를 추가합니다.

if (IsAdministrator() == false)
{
    try
    {
        ProcessStartInfo procInfo = new ProcessStartInfo();
        procInfo.UseShellExecute = true;
        procInfo.FileName = Application.ExecutablePath;
        procInfo.WorkingDirectory = Environment.CurrentDirectory;
        procInfo.Verb = "runas";
        Process.Start(procInfo);
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message.ToString());
    }

    return;
}

[C#] Text 파일 쓰기

C#에서 텍스트에 대한 인코딩을 지정하면서 텍스트 파일을 생성하고 텍스트를 기록하는 코드에 대해 정리해 봅니다.

using (System.IO.StreamWriter file = 
    new System.IO.StreamWriter(
        GeodataFileName, false, Encoding.GetEncoding("EUC-KR")))
{
    file.WriteLine("안녕하세요.");
}

위의 코드는 인코딩을 EUC-KR로 하기 위해 StreamWriter의 생성자에의 세번째 인자에 인코딩 정보를 전달했으며 두번째 인자를 false로 하여 텍스트 파일이 새롭게 생성되도록 하고 있습니다. 만약 두번째 인자를 true로 지정하면 기존의 파일에 텍스트 값을 덧붙여(Append) 기록하게 됩니다.

[C++11] decltype

decltype은 주어진 표현식에 대한 결과의 타입을 컴파일러가 추론하라는 키워드(keyword)입니다. 예를 들어서 다음의 코드를 보면..

#include "stdafx.h"
#include 

using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
    cout << typeid(decltype(10)).name() << endl;

    return 0;
}

위 코드에서 8번을 보면 decltype(10)이라는 코드가 있는데, 표현식 10에 해당하는 type을 컴파일러가 추론을 하여 해당 타입의 이름을 출력하게 되는 것으로 결과는 'int'를 출력합니다.

또 다른 예를 살펴보면..

#include "stdafx.h"
#include 

using namespace std;

auto func(int a, int b) -> decltype(a + b)
{
    return a + b;
}

int _tmain(int argc, _TCHAR* argv[])
{
    cout << func(100, 200) << endl;

    return 0;
}

6번 코드를 보면 함수의 결과값에 auto를 사용할 수 없음에도 func라는 함수의 반환값이 auto를 사용하고 있습니다. 이것이 가능한 이유는 바로 함수의 정의 뒤에 오는 -> decltype(a+b)에 의해서 입니다. 즉, a+b에 대한 결과값의 타입을 추론하여 ->에 의해 함수의 반환값 추론에 대한 힌트를 제공하는 것입니다. a와 b는 int 타입이고 이 int 값들의 합 역시 int이므로 쉽게 함수의 결과값의 타입은 int라는 것을 추론할 수 있는 것입니다.