[ System.Data.SqlClient.SqlConnection ]
- Connection String은 app.config에 connectionStrings에 정의해두고 시작한다.
(https://staticvoidlife.tistory.com/80)
- 아래와 같이 연결하면 된다. 참고로 SqlConnection은 IDisposable 인터페이스를 구현한다.
using System;
using System.Configuration;
using System.Data.SqlClient;
class Program
{
static void Main(string[] args)
{
string connectionString = ConfigurationManager.ConnectionStrings["TestDB"].ConnectionString;
SqlConnection sqlCon = new SqlConnection();
sqlCon.ConnectionString = connectionString;
sqlCon.Open();
sqlCon.Close();
}
}
[ System.Data.SqlClient.SqlCommand ]
- DB에 연결하고 나서, SqlCommand를 이용하여 SELECT, UPDATE, DELETE 등의 쿼리를 수행할 수 있다.
- INSERT, UPDATE, DELETE는 ExecuteNonQuery()로 실행한다.
- SELECT는 1개 값 반환의 경우 ExecuteScalar, 다중 레코드 반환 필요시 ExecuteReader를 사용한다.
- ★ ExecuteReader는 사용후 반드시 Close 해줄 것!!!
using System;
using System.Configuration;
using System.Data.SqlClient;
class Program
{
static void Main(string[] args)
{
string connectionString = ConfigurationManager.ConnectionStrings["TestDB"].ConnectionString;
SqlConnection sqlCon = new SqlConnection();
sqlCon.ConnectionString = connectionString;
sqlCon.Open();
// INSERT
SqlCommand cmd = new SqlCommand();
cmd.Connection = sqlCon;
cmd.CommandText = "INSERT INTO MemberInfo(Name, Birth, Email, Family) VALUES('Fox', '1970-01-25', 'fox@gmail.com', 5)";
int affectedCount = cmd.ExecuteNonQuery();
Console.WriteLine(affectedCount);
// UPDATE
cmd = new SqlCommand();
cmd.Connection = sqlCon;
cmd.CommandText = "UPDATE MemberInfo SET Family=3 WHERE Email = 'fox@gmail.com'";
affectedCount = cmd.ExecuteNonQuery();
Console.WriteLine(affectedCount);
// DELETE
cmd = new SqlCommand();
cmd.Connection = sqlCon;
cmd.CommandText = "DELETE FROM MemberInfo WHERE Email = 'fox@gmail.com'";
affectedCount = cmd.ExecuteNonQuery();
Console.WriteLine(affectedCount);
// SELECT (단일)
cmd = new SqlCommand();
cmd.Connection = sqlCon;
cmd.CommandText = "SELECT COUNT(*) FROM MemberInfo WHERE Family >= 2";
object objValue = cmd.ExecuteScalar();
int countOfMember = (int)objValue;
Console.WriteLine(countOfMember);
// SELECT (여러개) - System.Data.SqlClient.SqlDataReader
cmd.CommandText = "SELECT * FROM MemberInfo";
SqlDataReader reader = cmd.ExecuteReader();
while (reader.Read()) // 끝까지 읽었으면 false
{
string name = reader.GetString(0);
DateTime birth = reader.GetDateTime(1);
string email = reader.GetString(2);
byte family = reader.GetByte(3);
Console.WriteLine("{0}, {1}, {2}, {3}", name, birth, email, family);
}
reader.Close(); // Close 필요
sqlCon.Close();
}
}
[ System.Data.SqlClient.SqlParameter ]
- User에게 입력받은 데이터로 SqlCommand를 이용해서 command를 수행시, CommandText에 문자열 연산으로 처리해버리면 SQL Injection 보안에 취약해지며 단일 쿼리문으로 수행되므로 동일한 쿼리가 발생할 확률이 낮아지므로 캐시로 인한 성능이 좋지 않다.
- 이를 개선하기 위해 매개변수화된 쿼리(parameterized query)를 이용한다. 이는 System.Data.SqlClient.SqlParameter 클래스를 사용한다.
using System;
using System.Configuration;
using System.Data.SqlClient;
using System.Data;
class Program
{
static void Main(string[] args)
{
string connectionString = ConfigurationManager.ConnectionStrings["TestDB"].ConnectionString;
// 아래 4개 변수는 입력 받은 변수로 가정
string name = "Cooper";
DateTime birth = new DateTime(1990, 2, 7);
string email = "cooper@hotmail.com";
int family = 5;
using (SqlConnection sqlCon = new SqlConnection())
{
sqlCon.ConnectionString = connectionString;
sqlCon.Open();
SqlCommand cmd = new SqlCommand();
cmd.Connection = sqlCon;
// @Name 파라미터 준비
SqlParameter paramName = new SqlParameter("Name", SqlDbType.NVarChar, 20);
paramName.Value = name;
// @Birth 파라미터 준비
SqlParameter paramBirth = new SqlParameter("Birth", SqlDbType.Date);
paramBirth.Value = birth;
// @Email 파라미터 준비
SqlParameter paramEmail = new SqlParameter("Email", SqlDbType.NVarChar, 100);
paramEmail.Value = email;
//@Family 파라미터 준비
SqlParameter paramFamily = new SqlParameter("Family", SqlDbType.TinyInt);
paramFamily.Value = family;
// cmd.Parameters 컬렉션에 SqlParameter 개체 추가
cmd.Parameters.Add(paramName);
cmd.Parameters.Add(paramBirth);
cmd.Parameters.Add(paramEmail);
cmd.Parameters.Add(paramFamily);
cmd.CommandText = "INSERT INTO MemberInfo(Name, Birth, Email, Family) VALUES (@Name, @Birth, @Email, @Family)";
int affectedRows = cmd.ExecuteNonQuery();
Console.WriteLine(affectedRows);
}
}
}
[ System.Data.SqlClient.SqlDataAdapter ]
- 데이터베이스 연동 프로그램을 만들다 보면 사실상 거의 모든 작업이 SELECT에 집중된다는 것을 알 수 있다.
- SqlConnection 객체의 연결이 장시간 지속되지 않도록 최대한 데이터를 빨리 읽어내어 DataSet 개체에 채워넣고 곧바로 연결 개체의 사용을 중지한다.
using System;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
namespace ConsoleApp
{
class Program
{
static void Main(string[] args)
{
string connectionString = ConfigurationManager.ConnectionStrings["TestDB"].ConnectionString;
DataSet ds = new DataSet();
using (SqlConnection sqlCon = new SqlConnection(connectionString))
{
SqlDataAdapter sda = new SqlDataAdapter("SELECT * FROM MemberInfo", sqlCon);
sda.Fill(ds, "MemberInfo");
}
ds.WriteXml(Console.Out);
}
}
}
[ 데이터베이스 트랜잭션 - System.Data.SqlClient.SqlTransaction ]
- 다수의 쿼리 실행히 모두 실패하거나 모두 성공하는 논리적 단위
- 트랜잭션을 사용하면, 아래 4가지 특성(앞글자만 따서 ACID)이 보장된다.
1 - 원자성(Atomicity) : 트랜잭션과 관련된 작업이 모두 수행되거나 수행되지 않음을 보장한다.
2 - 일관성(Consistency): 트랜잭션 실행을 완료하면 ㅇ너제나 일관성 있는 데이터베이스 상태로 유지하는 것을 의미한다.
3 - 고립성(Isolation) : 트랜잭션을 수행할 때 다른 트랜잭션의 연산 작업이 끼어들지 못하게 보장하는 것을 의미한다.
4 - 지속성(Durability) : 성공적으로 수행된 트랜잭션을 영원히 반영되어야 하며, 모든 트랜잭션은 로그가 남아 시스템 장애가 발생하기 전 상태로 되돌릴 수 있다.
- 기본적인 형태는 아래와 같다. Commit()이 수행되지 않거나 SqlTransaction.Abort()를 호출하면 그 트랜잭션은 실패처리된다.
using System;
using System.Configuration;
using System.Data.SqlClient;
class Program
{
static void Main(string[] args)
{
string connectionString = ConfigurationManager.ConnectionStrings["TestDB"].ConnectionString;
using (SqlConnection sqlCon = new SqlConnection())
{
sqlCon.ConnectionString = connectionString;
sqlCon.Open();
using (SqlTransaction transaction = sqlCon.BeginTransaction())
{
SqlCommand cmd = new SqlCommand();
cmd.Connection = sqlCon;
cmd.Transaction = transaction;
// SqlCommand 처리
transaction.Commit();
}
}
}
}
- SqlCommand마다 일일이 트랜잭션 변수를 대입하면 불편하다. 이를 해소하기 위해 .NET 2.0에 System.Transactions.TransactionScope 타입이 추가되었다. (System.Transaction.dll 어셈블리 참조 추가가 필요하며, Connection Open되기 전에 미리 생성되어있어야 한다.)
using System;
using System.Configuration;
using System.Data.SqlClient;
using System.Transactions;
class Program
{
static void Main(string[] args)
{
string connectionString = ConfigurationManager.ConnectionStrings["TestDB"].ConnectionString;
using (SqlConnection sqlCon = new SqlConnection(connectionString))
{
using (TransactionScope tx = new TransactionScope())
{
sqlCon.Open();
string txt = "INSERT INTO MemberInfo(Name, Birth, Email, Family) VALUES('{0}', '{1}', '{2}', '{3}')";
SqlCommand cmd = new SqlCommand();
cmd.Connection = sqlCon;
cmd.CommandText = string.Format(txt, "Fox", "1970-01-25", "fox@gmail.com", "5");
Console.WriteLine(cmd.ExecuteNonQuery());
txt = "DELETE FROM MemberInfo WHERE Email = 'fox@gmail.com'";
cmd.CommandText = txt;
Console.WriteLine(cmd.ExecuteNonQuery());
tx.Complete();
}
}
}
}
'Programming > C#' 카테고리의 다른 글
| 리플렉션(Reflection) (0) | 2019.03.12 |
|---|---|
| MSSQL Database 연동(2) (0) | 2019.03.11 |
| app.config (0) | 2019.03.05 |
| [네트워크 프로그래밍] Http 통신 (0) | 2019.03.02 |
| [네트워크 프로그래밍] TCP/IP 예제 (0) | 2019.02.27 |