본문 바로가기
Dotnet/Blazor

Ado.net 그리고 DataTable, DataSet, DataRow에 대해서 알아봅시다.

by 잘먹는 개발자 에단 2024. 7. 22.

들어가면서

사실 DataTable, DataSet, DataRow는 Blazor에 대한건 아니고, 디비에서 데이트 가져와서 처리할 때 주로 쓰이는 클래스들입니다.

 

프론트엔드 개발을 하면 우리가 사실 api를 짤 일은 거의 없습니다. 보통은 rest api 쓰는 거에서 그치는데, 마소(마이크로소프트)에서 만든 것들을 보면, 아예 쿼리까지 짜서 한번에 가져오거나 (ado.net) 아니면 디비 설계부터 수정까지 전부 원스톱으로 끝내버리는 (Entity Framework) .... 그런 방법을 쓰더라구요.

 

 

EF 같은 경우는 편하긴하지만, 수정하는게 너무 복잡합니다. 그리고 기존의 데이터베이스를 모델에 동기화 시키는데에 있어서 예기치 않은 문제점이 너무 많이 발생했어요. 이 부분은 추후에 정리해서 다루겠습니다.

 

 

그래서 만약에 C# 베이스인 Blazor나 asp.net web forms를 쓴다 근데 데이터베이스에서 바로 가져와야한다.. 고 하면 그냥 마음 편하게 ado.net 쓰는게 좋을 것 같아요.

 

주저리주저리가 길어졌는데 한번 들어가 볼까요?

 

 

일단 상황부터 가정해볼게요.

 

우리는 SQL SERVER를 연결할거에요

서버는 Ethan

데이터베이스는 TestDb1

UserId는 ethan

password는 ethanspw라고 하겠습니다.

 

 

그러면 먼저 connect string을 설정해줘야 합니다.

private static readonly string conn = 
"Server = Ethan; Database = TestDb1; User Id = ethan; password = ethanspw;"

 

 

프론트에서 필요한 라이브러리가 있으면 우리는 npm이나 yarn을 흔히 쓰죠? 

여기에서는 Nuget이라는 것을 사용합니다.

Sql Server를 연결하려면 몇가지 패키지가 필요해요.

 

다음 패키지들을 다운로드 받아줍니다.

System.Data.SqlClient

System.Data

 

그러면 이제 여러 클래스들을 사용할 수 있게 됩니다.  ( SqlCommand, SqlConnection 등.... )

 

internal class UseDatabase{
	
    // 연결문자열 (가정해서)
    private static readonly string conn = "Server = Ethan; Database = TestDb1; User Id = ethan; password = ethanspw;"
	
    public static DataTable GoQuery(string sqlQuery){
    	DataTable dt = new DataTable();
        
        using(SqlConnection connection = new SqlConnection(conn)){
        	connection.Open();
            
            using(SqlCommand command = new Command(sqlQuery, connection)){
            	using(SqlDataAdapter adapter = new SqlDataAdapter()){
                	adapter.Fill(dt);
                }
            }
        }
        return dt;
    }
}

 

보통 짠다면 이런식으로 우리는 정적 메서드로 해서 데이터베이스에서 쿼리를 실행하는 코드를 짜줍니다.

 

근데, 여기에서 여간 신경이 쓰이는게 바로 저놈, DataTable입니다.

 

저걸로 반환했으니까 저걸 다룰 줄 알아야 페이지에서 뿌리든가 할 수 있어요. 

 

 

 

그래서 다음으로는 DataTable 그리고 또 디비에서 가져온 데이터를 다룰 수 있는 클래스들에 대해서 알아보겠습니다. 

 

챗지피티한테 그려달라니까 이렇게 그려줬네요. 오히려 보면 더 헷깔리는 것 같아요.

 

 

 

DataRow < DataTable < DataSet 

 

 

다음은 DataTable입니다.

아이디 이름 나이
1 존슨 20
2 벤슨 21

 

 

여기에서 첫번째 행(Row)만 가져오면 이게 DataRow입니다.

1 존슨 20

 

 

DataTable이 여러개 겹쳐있다면 ( 3차원 배열을 생각해주세요! )

아이디 이름 나이
1 존슨 20
2 벤슨 21
아이디 이름 나이
3 닉슨 20
4 넥슨 21
아이디 이름 나이
5 니슨 20
6 쟌슨(빌) 21

 

이게 3차원으로 겹쳐있다고 생각하면 그건 DataSet입니다.

 

사실 DataSetd은 거의 다룰일이 없고, DataTable과 DataRow만 주구장창 다루게 됩니다.

 

 

 

DataTable 

- 데이터 테이블은 데이터베이스의 테이블을 메모리 내에서 표현한 것입니다.

- 데이터테이블 객체는 행(DataRow)과 열(DataColumn)으로 구성됩니다.

 

// DataTable 객체 생성
DataTable table = new DataTable("SampleTable");

// 열 추가
table.Columns.Add("ID", typeof(int));
table.Columns.Add("Name", typeof(string));

// 행 추가
DataRow row = table.NewRow(); // 새로운 DataRow 생성
row["ID"] = 1;
row["Name"] = "John";
table.Rows.Add(row); // 행을 DataTable에 추가

// 테이블의 모든 행 출력
foreach (DataRow dataRow in table.Rows)
{
    Console.WriteLine($"ID: {dataRow["ID"]}, Name: {dataRow["Name"]}");
}

 

 

DataRow

- 데이터행은 데이터테이블의 한 행을 나타냅니다. 

- 각 열에 대한 데이터를 저장하고 있습니다. 

 

// DataRow 생성 및 데이터 설정
DataRow row = table.NewRow();
row["ID"] = 2;
row["Name"] = "Doe";
table.Rows.Add(row);

// 행 데이터 수정
row.BeginEdit();
row["Name"] = "Jane";
row.EndEdit();

 

 

 

 

그럼 이제, 아까 우리가 봤던 이 테이블 testtable에서 아이디 2 가 넘어가는 것중에 가장 첫번째의 행을 가져와서 무언가를 해보는 코드를 작성해보겠습니다. 

아이디 이름 나이
1 존슨 20
2 벤슨 21
3 닉슨 20
4 넥슨 21

 

 

using System;
using System.Data;
using System.Data.SqlClient;

internal class UseDatabase
{
    // 연결문자열 (가정해서)
    private static readonly string conn = "Server = Ethan; Database = TestDb1; User Id = ethan; password = ethanspw;";
    
    public static DataTable GoQuery(string sqlQuery)
    {
        DataTable dt = new DataTable();
        
        using (SqlConnection connection = new SqlConnection(conn))
        {
            connection.Open();
            
            using (SqlCommand command = new SqlCommand(sqlQuery, connection))
            {
                using (SqlDataAdapter adapter = new SqlDataAdapter(command))
                {
                    adapter.Fill(dt);
                }
            }
        }
        
        return dt;
    }
}

class Program{
	static void Main(string[] args){
    	string query = "SELECT name, age from testTable WHERE id > 2"
        
        
        DataTable resultTable = UseDatabase.GoQuery(query);
        
        if(resultTable.Row.Count >0){
        	DataRow firstRow = resultTable.Rows[0];
            
            string name = firstRow["name"].ToString();
            string age = firstRow["age"].ToString();
            
            Console.WriteLine($"이름은 {name}이고 나이는 {age}살이야");
        }else{
        	Console.WriteLine("데이터 없어요");
        }
    }
}

 

결국에 짜잔 이런식으로 쓸 수 있습니다.

 

사실 인자 받아서 쿼리에 파라미터 주고 처리하고 이러면 더 머리아프긴한데,,, ( SQL 인젝션 문제가 생긴다던지.... ) 기본적인건 이렇습니다.

 

그 머리 아픈건 다음에 천천히 다뤄볼게요.