Dapper ORM 사용 예제

2024. 10. 22. 20:33·C#.NET/C#

ADO.NET과 가장 동일하며 쿼리문을 직접 제어할 때 사용되는 Dapper 에 대한 사용법을 정리해 보았다.

- Dapper ORM 은 일반적으로 MSSQL, MYSQL(MariaDB), Oracle, PostgreSQL, SQLite를 지원하며 이 밖에 다른 프로바이더
들도 지원할 수 있다.
- Dapper 는 오픈 소스이다 (https://github.com/DapperLib/Dapper)
- NuGet 패키지를 통해 설치 가능하다 (https://www.nuget.org/packages/dapper)
- 연결문자열을 만들기 위해 MSSQL 기준 NetCore 에서는 System.Data.SqlClient 를 NuGet 에서 받아야 할 수 있다.
- NET의 ORM중 EFCore 대비 높은 성능을 보여준다. 


아래의 예제는 Dapper 2.1 버전에서 작성 되었습니다. (구버전일 경우 사용법이 조금 다를 수 있음을 참고해 주세요)


A. 준비작업
 - 클래스 상단에 커넥션 문자열을 작성한 예시

public class HomeController : Controller
{	
	private readonly string _connectionString = @"Server=127.0.0.1;Database=DogDB2;User Id=dog;Password=123456;TrustServerCertificate=True;";    
}

 

B. Sql 쿼리에는 반드시 SqlParameter 를 사용하자.
 - 인잭션 공격에 대해 어느정도 방어 효과가 있다. 
 - 즉 "WHERE Name = '" + DOG + "'  "  문자열 더하기는 좋지 않다.
 - 프로시저가 아닌 SQL문에 대해서 WHERE Name = '@Name' 이 아닌
  WHERE = @Name 으로 사용해야 한다 즉 홀따옴표 '' 는 제거해야 정상 작동한다.

 

 

1. Execute() 는 SQL 명령어를 실행할 떄 사용되는 메소드이다.
- ADO.Net에서 ExecuteNonQuery() 이것과 비슷하게 사용된다.

- 반환값이 void 가 아니라 실행으로 인해 int로 영향을 받는 행의 갯수를 반환 한다
- 성능이슈로 프로시저 작성시  SET NOCOUNT ON; 옵션을 사용하기에 void 처럼 사용하는것이
일반적이다.

- 주로 조회가 아닌 등록,수정,삭제,테이블생성 등에 사용된다

        /// <summary>
        /// Execute 는 쿼리를 실행할 때 사용된다. (Create, Insert, Update, Delete...)
        /// </summary>
        /// <returns></returns>
        [Route("index")]
        public JsonResult Index()
        {            
            using (IDbConnection con = new SqlConnection(_connectionString))
            {
                // Execute
                string queryCreate = @"
                    CREATE TABLE [dbo].[Dog](
	                    [DogId] [int] IDENTITY(1,1) NOT NULL,
	                    [Name] [varchar](30) NULL,
	                    [Address] [varchar](100) NULL,
	                    [Zipcode] [varchar](10) NULL,
	                    [Tel] [varchar](20) NULL,
	                    [CreateDate] [smalldatetime] NULL
                    )                    
                ";

                con.Execute(queryCreate);

                // Execute (데이터 Insert)
                var p = new DynamicParameters();
                p.Add("@Name", "김도그");
                p.Add("@Address", "서울시 강남구 다리밑");
                p.Add("@Zipcode", "10000");
                p.Add("@Tel", "01012341234");
                p.Add("@CreateDate", DateTime.Now);

                string queryInsert = @"
                    INSERT INTO [dbo].[Dog]
                               ([Name]
                               ,[Address]
                               ,[Zipcode]
                               ,[Tel]
                               ,[CreateDate])
                         VALUES
                               (@Name
                                ,@Address
                                ,@ZipCode
                                ,@Tel
                                ,@CreateDate)
                ";

                con.Execute(queryInsert, p);

            }

            return Json("ok");            
        }

        /// <summary>
        /// Execute 를 비동기로 실행한다
        /// </summary>
        /// <returns></returns>
        [Route("index2")]
        public async Task<JsonResult> Index2()
        {            
            using (IDbConnection con = new SqlConnection(_connectionString))
            {
                string queryInsertAsync = @"
                    INSERT INTO [dbo].[Dog]
                               ([Name]
                               ,[Address]
                               ,[Zipcode]
                               ,[Tel]
                               ,[CreateDate])
                         VALUES
                               (@Name
                                ,@Address
                                ,@ZipCode
                                ,@Tel
                                ,@CreateDate)
                ";

                var p2 = new DynamicParameters();
                p2.Add("@Name", "이도그");
                p2.Add("@Address", "서울시 서초구 다리밑");
                p2.Add("@Zipcode", "10002");
                p2.Add("@Tel", "01012341235");
                p2.Add("@CreateDate", DateTime.Now);

                await con.ExecuteAsync(queryInsertAsync, p2);
            }

            return Json("ok");
        }

 

2. Query() 는 SQL 의 SELECT 결과를 반환한다.
 - 레코드셋, 레코드 단일, 스칼라, 멀티레코드 형식을 지원한다

using (IDbConnection con = new SqlConnection(_connectionString))
{   
    // 1. List 에 담기 (여러마리의 도그 정보를 가져옴)
    string query = @"
        SELECT *
        FROM DOG WITH(NOLOCK)                    
    ";

    var list = con.Query<Dog>(query, null).ToList();


    // 2. 하나의 Dog에 담기
    var p = new DynamicParameters();
    p.Add("@Name", "김도그");

    string querySingle = @"
        SELECT *
        FROM DOG WITH(NOLOCK)
        WHERE Name = @Name
    ";

    // 두가지 방법중 하나를 선택해서 사용
    Dog? dog = con.QuerySingleOrDefault<Dog>(querySingle, p);
    //Dog dog2 = con.Query<Dog>(querySingle, p).Single();


    // 3. 쿼리의 첫번째 1행1열 1개의 반환 값 (Scalar)
    var p2 = new DynamicParameters();
    p2.Add("@Name", "이도그");

    string queryScalar = @"
        SELECT *
        FROM DOG WITH(NOLOCK)
        WHERE Name = @Name
    ";

    int dogID = con.QueryFirst<int>(querySingle, p2);

    // 4. 쿼리 결과에 대해 여러개 받기
    string queryMulti = @"
        SELECT COUNT(*) AS Count
        FROM DOG WITH(NOLOCK)

        SELECT *
        FROM DOG WITH(NOLOCK)
    ";

    using (var multiResult = con.QueryMultiple(queryMulti))
    {
        // 첫 번째 결과 집합
        int count = multiResult.ReadSingle<int>();

        // 두 번째 결과 집합
        List<Dog> dogList = multiResult.Read<Dog>().AsList();
    }
}

 

3. 프로시저 사용 및 Output 파라미터 받기
- GetDogName 이란 프로시저를 통해 Output 파라미터 가져오기
a) SQL

CREATE PROCEDURE GetDogName
    @DogID int,
    @OutputName NVARCHAR(50) OUTPUT
AS
BEGIN
    SELECT TOP 1 @OutputName = Name
    FROM DOG WITH(NOLOCK)
    WHERE DogId = @DogID
END


 b) C#

  using (IDbConnection con = new SqlConnection(_connectionString))
  {
      var p3 = new DynamicParameters();
      p3.Add("@DogID", 1);
      p3.Add("@OutputName", dbType: DbType.String, size: 50, direction: ParameterDirection.Output);

      con.Execute("GetDogName", p3, commandType: CommandType.StoredProcedure);

      string dogName = p3.Get<string>("@OutputName");
  }

 

4. 프로시저 사용 및 Return 파라미터 받기

 - INSERT 나 UPDATE 또는 DELETE의 처리 결과를 INT로 받을 때  주로 Return 파라미터를 사용한다

 a) SQL

CREATE PROCEDURE DogInsert
    @Name NVARCHAR(50),
    @Address NVARCHAR(100),
    @ZipCode NVARCHAR(10),
    @Tel NVARCHAR(15),
    @CreateDate DATETIME
AS
BEGIN

	BEGIN TRY

    	INSERT INTO [dbo].[Dog] ([Name], [Address], [Zipcode], [Tel], [CreateDate])
    	VALUES (@Name, @Address, @ZipCode, @Tel, @CreateDate);
    
    	RETURN 1;
        
    END TRY
    BEGIN CATCH
    
    	RETURN 0;
        
    END CATCH
    
END

 

b) c#

using (IDbConnection con = new SqlConnection("YourConnectionStringHere"))
{
    var p = new DynamicParameters();
    p.Add("@Name", "누렁이");
    p.Add("@Address", "경기도 안산시 공단");
    p.Add("@ZipCode", "12345");
    p.Add("@Tel", "01012345678");
    p.Add("@CreateDate", DateTime.Now);
    p.Add("ReturnValue", dbType: DbType.Int32, direction: ParameterDirection.ReturnValue);

    con.Execute("DogInsert", p, commandType: CommandType.StoredProcedure);
    int returnValue = p.Get<int>("ReturnValue");
}

 

 

5. 위 2번 Query() 를 비동기 형태 호출로 변경한 예제
 - 컨트롤러의 반환부분이 async Task<> 이며 
 - dapper 메소드 실행부가 await 키워드와 메소드 뒤에 Async 로 변경되어 있는 차이니 응용하여 사용하자

public async Task<JsonResult> Index2()
{
    string name = string.Empty;

    using (IDbConnection con = new SqlConnection(_connectionString))
    {
        // 1. List 에 담기 (여러마리의 도그 정보를 가져옴)
        string query = @"
            SELECT *
            FROM DOG WITH(NOLOCK)                    
        ";

        var list = (await con.QueryAsync<Dog>(query)).ToList();

        // 2. 하나의 Dog에 담기
        var p = new DynamicParameters();
        p.Add("@Name", "김도그");

        string querySingle = @"
            SELECT *
            FROM DOG WITH(NOLOCK)
            WHERE Name = @Name
        ";

        // 두가지 방법중 하나를 선택해서 사용
        Dog? dog = await con.QuerySingleOrDefaultAsync<Dog>(querySingle, p);
        //Dog dog2 = (await con.QueryAsync<Dog>(querySingle, p)).Single();

        // 3. 쿼리의 첫번째 1행1열 1개의 반환 값 (Scalar)
        var p2 = new DynamicParameters();
        p2.Add("@Name", "이도그");

        string queryScalar = @"
            SELECT *
            FROM DOG WITH(NOLOCK)
            WHERE Name = @Name
        ";

        int dogID = await con.QueryFirstAsync<int>(queryScalar, p2);

        // 4. 쿼리 결과에 대해 여러개 받기
        string queryMulti = @"
            SELECT COUNT(*) AS Count
            FROM DOG WITH(NOLOCK)

            SELECT *
            FROM DOG WITH(NOLOCK)
        ";

        using (var multiResult = await con.QueryMultipleAsync(queryMulti))
        {
            // 첫 번째 결과 집합
            int count = multiResult.ReadSingle<int>();

            // 두 번째 결과 집합
            List<Dog> dogList = (await multiResult.ReadAsync<Dog>()).AsList();
        }
    }

    return Json("ok");
}

 

'C#.NET > C#' 카테고리의 다른 글

C# 에서 POST로 API 보내기  (0) 2025.07.15
Spring의 Class ToString 을 비슷하게 구현해보자  (0) 2024.09.20
간단 텍스트 파일 로그 생성  (0) 2024.09.06
c# 권장 코딩 규칙 가이드  (0) 2020.06.09
C#을 통한 Javascript 압축 (한글불가)  (0) 2020.06.03
'C#.NET/C#' 카테고리의 다른 글
  • C# 에서 POST로 API 보내기
  • Spring의 Class ToString 을 비슷하게 구현해보자
  • 간단 텍스트 파일 로그 생성
  • c# 권장 코딩 규칙 가이드
iyak
iyak
자료 정리
  • iyak
    iyak
    나의 정리 공간

    post | manage
  • 전체
    오늘
    어제
    • 분류 전체보기 (33)
      • C#.NET (14)
        • C# (6)
        • ASP.NET (7)
        • WinForm (0)
        • 설정 (1)
      • JAVA,Spring (0)
        • Spring (0)
      • DB (9)
        • SQLServer (9)
        • MySQL & MaridDB (0)
      • Web (9)
        • JS & jQuery (7)
        • Web개발 관련사이트 (2)
      • 기타 (1)
        • 프로그램 (1)
  • 블로그 메뉴

    • 홈
    • 태그
  • 링크

  • 공지사항

  • 인기 글

  • 태그

  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.0
iyak
Dapper ORM 사용 예제
상단으로

티스토리툴바