Dapper?
Dapper는 오픈 소스 Object Relational Mapper(ORM)로 성능과 편의성에 집중하여 다른 ORM에 비해 매우 빠르다. 또한, C# SqlConnector만으로 DB 프로그래밍을 하기에는 번거로움이 많아 Dapper.Net을 사용하여 간단하게 DB 프로그래밍을 할 수 있다.
Dapper Install
Dapper.Net은 Nuget을 통해 설치가 가능하다.
Development Environment
VisualStudio 2019
.Net Core 5.0
MS SQL
How To Use
SQL Connect
기존 C#에서 Database에 연결할 때 사용하는 System.Data.SqlClient 통해 Database에 연결한다.
- NuGet Packages
- Microsoft.Extensions.Configuration
 - Microsoft.Extensions.Configuration.Binder
 
 
Database 연결 사전 준비
Database 주소, 아이디, 패스워드 등 연결을 위한 기본 정보들을 설정파일로 부터 불러와 Connection String으로 만든다.
namespace Utility.Database
{
	[System.Serializable]
	public class Repository
	{
		[JsonProperty("idx")]
		public int idx { get; set; }
		[JsonProperty("host")]
		public string host { get; set; }
		[JsonProperty("port")]
		public string port { get; set; }
		[JsonProperty("cat_log")]
		public string cat_log { get; set; }
		[JsonProperty("user_id")]
		public string user_id { get; set; }
		[JsonProperty("password")]
		public string password { get; set; }
		[JsonIgnore]
		public SqlConnectionStringBuilder builder { get; private set; }
		public Repository Build()
		{
			builder = new SqlConnectionStringBuilder();
			builder.DataSource = host + "," + port;
			builder.UserID = user_id;
			builder.Password = password;
			builder.InitialCatalog = cat_log;
			return this;
		}
	}
	public class Factory
	{
		public List<Repository> repository_list;
	}
}
namespace Utility.Database
{
	/**
	 * Using MSSQL
	 * **/
	public class SqlConnector
	{
		public static Factory Factory { get; set; }
		public static void IntializeSqlConnector(IConfiguration _conf)
		{
			try
			{
				var db_conf = _conf.GetSection("Database");
				SqlConnector.Factory = new Factory()
				{
					repository_list = new List<Repository>()
					{
						new Repository()
						{
							idx = db_conf.GetValue<int>("idx"),
							host = db_conf.GetValue<string>("host"),
							port = db_conf.GetValue<string>("port"),
							cat_log = db_conf.GetValue<string>("cat_log"),
							user_id = db_conf.GetValue<string>("user_id"),
							password = db_conf.GetValue<string>("password")
						}.Build()
					}
				};
			}
			catch (Exception ex)
			{
				throw new System.Exception("IntializeSqlConnector :: " + ex.ToString());
			}
		}
	}
}
Database 연결
namespace Utility.Database
{
	/**
	 * Using MSSQL
	 * **/
	public class SqlConnector
	{
    					.
       		 			.
        				.
		public static IDbConnection GetSqlConnection(int _idx = 0)
		{
			if (Factory == null)
				throw new System.Exception("GetSqlConnectrion :: factory is null");
			string strConn = null;
			Factory.repository_list.ForEach(action =>
			{
				if (action.idx == _idx)
					strConn = action.builder.ConnectionString;
			});
			if (strConn == null)
				throw new System.Exception($"not found repository idx ({_idx})");
			return new SqlConnection(strConn);
		}
	}
}
Database 연결은 SqlConnector.GetSqlConnection 함수를 통해 연결하도록 한다.
SqlConnector.IntializeSqlConnector(Configuration);
using (var conn = SqlConnector.GetSqlConnection())
{
	...
}
위와 같이 함수를 호출하여 사용하면 Database에 연결이 된다.
Query 전송
Dapper.Net 깃허브에 가면 더 많은 예제가 있다.
conn.Execute("insert into TB_TEST values (@a, @b)", new[]
{
	new {a = 1, b = "hi" },
	new {a = 2, b = "hello"}
});
public class TB_TEST
{
	public long ACCOUNT_SEQ;
	public string DATA;
}
var list = conn.Query<TB_TEST>("select * from TB_TEST where ACCOUNT_SEQ = @ACCOUNT_SEQ", new { ACCOUNT_SEQ = 1 }).AsList();
foreach (var item in list)
	Console.WriteLine(item.ACCOUNT_SEQ.ToString() + " / " + item.DATA.ToString());
Procedure 실행
namespace Utility.Models
{
	public class SqlParameter<KEY, VALUE> : Dictionary<KEY, VALUE>
	{
	}
}
namespace Utility.Database
{
	public class SqlExecutor
	{
		public static async Task<List<T>> GetAllAsync<T>(string _procedureName, SqlParameter<string, object> _paramters)
		{
			using var conn = SqlConnector.GetSqlConnection();
			return (await conn.QueryAsync<T>(_procedureName, new DynamicParameters(_paramters), commandType: System.Data.CommandType.StoredProcedure)).AsList();
		}
	}
}
var result = SqlExecutor.GetAllAsync<TB_TEST>("USP_TEST", new Utility.Models.SqlParameter<string, object> { { "@IN_ACCOUNT_SEQ", 1 }, { "@IN_DATA", "POWER" } });
result.Result.ForEach(delegate(TB_TEST data)
{
	Console.WriteLine("PROC :: " + data.ACCOUNT_SEQ + " / " + data.DATA);
});
주의 사항
기본적으로 Dapper는 쿼리 결과를 Buffer에 담아서 반환한다. 따라서, 쿼리 결과의 양이 많을 때는 Buffer 크기를 벗어나서 실패가 발생할 수도 있다.
Buffer 크기를 넘는 쿼리 결과를 받기 위해서는, Query 함수의 buffered 파라메터를 false로 세팅하면 된다.
참고
Dapper Tutorial :: dapper-tutorial.net/async
Async
Dapper Tutorial Dapper - Async Description Dapper also extend the IDbConnection interface with Async (asynchronous) methods: We only added a non-asynchronous version in this tutorial to make it easier to read. ExecuteAsync The ExecuteAsync can execute a co
dapper-tutorial.net
dapper-tutorial.net/knowledge-base/33745934/sqldatareader--buffered-vs-unbuffered-readers---how-to-
SqlDataReader: Buffered vs Unbuffered readers - How to?
As I recall, the difference between buffered and unbuffered is a call to the .ToList() extension method to force the objects to be materialised before the call to Query returns control to the caller. Essentially, when Dapper reads the database it can eithe
dapper-tutorial.net
'devops' 카테고리의 다른 글
| [Redis] Redis Sentinel + HAproxy (0) | 2021.08.08 | 
|---|---|
| [Docker] Jenkins & fabric (0) | 2021.07.25 | 
| MQTT/AMQP (0) | 2021.06.18 | 
| Volatile / Lock (0) | 2021.06.17 | 
| ASP.Net Core에서 NSwag 사용하기 (0) | 2021.02.14 |