Posting

Machbase의 최신 소식을 지금 만나보세요

Machbase C# Connector에서 Dapper.NET 사용

Dapper 소개

Dapper는 Stack Overflow 팀에서 개발한 오픈 소스 ORM(Object Relational Mapper)으로 가벼운 무게로 인해 다른 ORM에 비해 매우 빠르다.
Dapper는 성능과 사용 편의성을 염두에두고 제작되었으며, 트랜잭션, 저장 프로시저 또는 대량의 데이터 삽입을 사용하여 정적 및 동적 개체 바인딩을 모두 지원한다.

C# Connector 만으로 DB 프로그래밍을 하기에는 번잡한 것이 많다. 이런 경우 Dapper.NET을 사용하면 간단하게 DB 프로그래밍을 할 수 있다.
그냥 C# Connector를 사용하는 경우와 비교해도 성능차이는 거의 없다.

github : https://github.com/StackExchange/Dapper
github에서 성능비교표를 확인 할 수 있다.

Dapper 설치

Dapper.NET는 NuGet을 사용하여 설치한다.
Visual Studio 2017을 기준으로 설치방법을 설명하면 아래와 같다.

  1. 적용할 프로젝트를 open한 상태에서 도구 – NuGet 패키지 관리자 – 솔루션용 NuGet 패키지 관리 선택
  2. 찾아보기 탭에서 Dapper를 검색
  3. Dapper (또는 Dapper dot net)을 선택하여 설치
  4. 설치된 항목중에서 Dapper를 선택하면 Open 프로젝트 중에서 적용할 프로젝트를 선택하여 설치할 수 있다.

Dapper 사용방법

1. Query를 실행하고 결과를 typed List로 return 받는다.

public static IEnumerable Query(this IDbConnection cnn, string sql, object param = null, SqlTransaction transaction = null, bool buffered = true)
public class Dog
{
    public int Age { get; set; }
    public Guid Id { get; set; }
    public string Name { get; set; }
    public float Weight { get; set; }
}
 
var guid = Guid.NewGuid();
var dog = connection.Query("select Age = @Age, Id = @Id FROM DOGS", new { Age = 1, Id = guid });

Assert.Equal(1,dog.Count());
Assert.Null(dog.First().Age);
Assert.Equal(guid, dog.First().Id);

2. Query를 실행하고 결과를 dynamic objects로 return 받는다.

public static IEnumerable Query (this IDbConnection cnn, string sql, object param = null, SqlTransaction transaction = null, bool buffered = true)
var rows = connection.Query("select 1 A, 2 B FROM M$SYS_USERS union all select 3, 4 FROM M$SYS_USERS");
 
Assert.Equal(1, (int)rows[0].A);
Assert.Equal(2, (int)rows[0].B);
Assert.Equal(3, (int)rows[1].A);
Assert.Equal(4, (int)rows[1].B);

3. 결과를 return하지 않는 Query를 실행한다.

public static int Execute(this IDbConnection cnn, string sql, object param = null, SqlTransaction transaction = null)
connection.Execute(@"create table t1 (id varchar(20), i1 integer, i2 long)");

4. 3.과 같지만 list parameter인 경우 중복 실행 한다.

var count = connection.Execute(@"insert MyTable(colA, colB) values (@a, @b)",
    new[] { new { a=1, b=1 }, new { a=2, b=2 }, new { a=3, b=3 } }
  );
Assert.Equal(3, count); // 3 rows inserted: "1,1", "2,2" and "3,3"

주의사항
Dapper는 기본적으로 쿼리 결과를 buffer에 담아서 반환한다. 따라서 Query 결과의 양이 엄청나게 많을 때는 buffer 크기를 벗어나서 실패가 발생할 수도 있다.

Sample

기존 방식의 source

public void DapperTest()
{
    using (MachConnection sConn = new MachConnection(Utility.SERVER_STRING))
    {
        sConn.Open();
        ExecuteQuery(sConn, "create table t1 (id varchar(20), i1 integer, i2 long)", ErrorCheckType.ERROR_CHECK_NO);
        ExecuteQuery(sConn, "insert into t1 values ('ID1', 11, 12)", ErrorCheckType.ERROR_CHECK_YES);
        ExecuteQuery(sConn, "insert into t1 values ('ID2', 21, 22)", ErrorCheckType.ERROR_CHECK_YES);
        ExecuteQuery(sConn, "insert into t1 values ('ID3', 31, 32)", ErrorCheckType.ERROR_CHECK_YES);
 
        output.WriteLine("========== (select * from t1)");
 
        using (MachCommand sCommand = new MachCommand("select * from t1", sConn))
        {
            MachDataReader sDataReader = sCommand.ExecuteReader();
            while (sDataReader.Read())
            {
                output.WriteLine(String.Format("{0} : {1}, {2}", sDataReader.GetValue(0),
                                                                 sDataReader.GetValue(1),
                                                                 sDataReader.GetValue(2)));
            }
        }
 
        output.WriteLine("========== (select * from t1 where id=@id)");
 
        using (MachCommand sCommand = new MachCommand("select * from t1 where id=@id", sConn))
        {
            sCommand.ParameterCollection.Add(new MachParameter { ParameterName = "@id", Value = "ID1" });
            MachDataReader sDataReader = sCommand.ExecuteReader();
            while (sDataReader.Read())
            {
                output.WriteLine(String.Format("{0} : {1}, {2}", sDataReader.GetValue(0),
                                                                 sDataReader.GetValue(1),
                                                                 sDataReader.GetValue(2)));
            }
        }
 
        ExecuteQuery(sConn, "drop table t1", ErrorCheckType.ERROR_CHECK_NO);
        sConn.Close();
    }
}
 
internal static void ExecuteQuery(MachConnection aConn, string aQueryString, ErrorCheckType aCheckType)
{
    using (MachCommand sCommand = new MachCommand(aQueryString, aConn))
    {
        try
        {
            sCommand.ExecuteNonQuery();
        }
        catch (Exception me)
        {
            switch (aCheckType)
            {
                case ErrorCheckType.ERROR_CHECK_YES:
                    throw me;
                case ErrorCheckType.ERROR_CHECK_NO:
                default:
                    break;
            }
        }
    }
}

Dapper 적용 source

public void DapperTest()
{
    using (MachConnection sConn = new MachConnection(Utility.SERVER_STRING))
    {
        sConn.Open();
        sConn.Execute("create table t1 (id varchar(20), i1 integer, i2 long);");
        sConn.Execute("insert into t1 values (@a, @b, @c)", new[] { new { a = "ID1", b = 11, c = 12 },
                                                                    new { a = "ID2", b = 21, c = 22 },
                                                                    new { a = "ID3", b = 31, c = 32 } });
 
 
        output.WriteLine("========== (select * from t1)");
 
        var sData = sConn.Query("select * from t1").ToList();
        foreach (var sItem in sData)
        {
            output.WriteLine(String.Format("{0} : {1}, {2}", sItem.id, sItem.i1, sItem.i2));
        }
 
        output.WriteLine("========== (select * from t1 where id=@id)");
 
        sData = sConn.Query("select * from t1 where id=@id", new {id="ID1"}).ToList();
        foreach (var sItem in sData)
        {
            output.WriteLine(String.Format("{0} : {1}, {2}", sItem.id, sItem.i1, sItem.i2));
        }
 
        sConn.Execute("drop table t1;");
        sConn.Close();
    }
}
 
public class sTest
{
    public string id { get; set; }
    public int i1 { get; set; }
    public long i2 { get; set; }
}

실행결과

========== (select * from t1)
ID3 : 31, 32
ID2 : 21, 22
ID1 : 11, 12
========== (select * from t1 where id=@id)
ID1 : 11, 12

마무리

Dapper는 DB 프로그래밍을 간편하게 해주는 유용한 도구이다. 직접 코딩하는 것에 비하여 실행속도가 크게 느려지지도 않으면서 코딩 분량을 많이 줄일 수 있다. (무엇보다도 편리하다.)

결과가 buffer에 담겨져서 return되는 것 때문에 대량의 data를 사용하는 경우에 주의해야 한다는 점만 조심한다면 사용하지 않을 이유가 없다고 생각된다.아직까지 사용해 보지않았다면 한번 사용해 보기를 권장한다.

연관 포스트

C언어로 Binary data를 Machbase에 넣기

1.개요 Data를 다루다 보면 numeric, varchar 형 데이터뿐만 아니라 JPG, PNG, MP3와 같은 Binary data도 database에 저장해야 할 때가 존재한다. 그러나 일반 data들과는 달리 Binary

[MACHBASE 연동] Android studio에서 JDBC 연결하기

마크베이스 기술지원본부 이현민 1. 개요 수많은 데이터들이 많은 환경에서 생성되고 있는 오늘날, 우리 현대인들의 동반자인 스마트폰 또한 데이터생성의 주체로써 또는 전달자로서 알게 모르게 그 구실을