SQL Server : MARS 기능
ADO.NET과 같은 클라이언트 API를 이용하여 SQL Server의 데이타를 가져올 때, SQL Server와 Connection을 계속 유지하면서 SQL Server의 Server side Cursor에서 데이타를 한 레코드씩 가져오는 방식, 일명 Firehose 모드를 사용할 수 있다. DataReader류의 클래스들이 이러한 방식을 취하는데, 이 방식은 하나의 Connection에서 하나의 Resultset만 Open하고 있어야 한다는 제약점이 있다. 이는 하나의 Connection에서 하나의 SqlCommand 만을 실행하여 하나의 SqlDataReader를 열고 완전히 사용한 후에 다시 SqlDataReader를 닫고, 순차적으로 다른 SqlCommand를 보내야 한다는 것을 의미한다. 이러한 단점을 보완하기 위하여 SQL Server 2005부터는 MARS (Multiple Active Result Sets)이라는 기능을 제공하기 시작했다. 이는 하나의 Connection에서 여러 SqlCommand를 사용해서 각각 다른 ResultSet들을 동시에 사용할 수 있도록 한 것이다. 기술적으로는 하나의 Connection에 여러 개의 논리적 세션을 만들어 각 세션마다 다른 ResultSet을 핸들링하도록 한 것이다. 이는 서버에서 각 세션별로 서로 다른 데이타를 보내는 기능을 지원하기 때문에 가능한 것이다.
C#에서 MARS를 사용하는 방법
MARS를 사용하기 위해서는 먼저 Connection을 맺을 때, MARS를 사용할 것 임을 지정해 주어야 한다 (디폴트로 MARS는 Disable되어 있다). 이를 위해 Connection String안에 MultipleActiveResultSets = True를 아래 예와 같이 추가해 준다. 일단 해당 Connection에 MARS가 Enable되어 있으면, 그리고 해당 서버가 MARS를 지원한다면 (예: SQL 2005 이상 버젼) 한 Resultset이 닫히기 전에도 다른 SqlCommand를 호출하여 다른 Resultset을 열어 사용할 수 있다. 아래 예제는 부서(Dept)별 사원데이타를 출력하는 예이다.
예제
static void Main(string[] args)
{
string strConn = "Data Source=.;Initial Catalog=MyDB;Integrated Security=SSPI;MultipleActiveResultSets=True";
SqlConnection conn = new SqlConnection(strConn);
conn.Open();
SqlCommand cmd = conn.CreateCommand();
cmd.CommandText = "SELECT * FROM Dept";
SqlDataReader deptRdr = cmd.ExecuteReader();
while (deptRdr.Read())
{
int dept_id = deptRdr.GetInt32(0);
Console.WriteLine("{0} : {1}", dept_id, deptRdr["Name"]);
SqlCommand cmd2 = conn.CreateCommand();
cmd2.CommandText = "SELECT * FROM Emp WHERE DeptID = " + dept_id;
SqlDataReader empReader = cmd2.ExecuteReader();
while (empReader.Read())
{
Console.WriteLine("\t{0} ({1})", empReader["Name"], empReader["EmpID"]);
}
empReader.Close();
}
deptRdr.Close();
conn.Close();
}
{
string strConn = "Data Source=.;Initial Catalog=MyDB;Integrated Security=SSPI;MultipleActiveResultSets=True";
SqlConnection conn = new SqlConnection(strConn);
conn.Open();
SqlCommand cmd = conn.CreateCommand();
cmd.CommandText = "SELECT * FROM Dept";
SqlDataReader deptRdr = cmd.ExecuteReader();
while (deptRdr.Read())
{
int dept_id = deptRdr.GetInt32(0);
Console.WriteLine("{0} : {1}", dept_id, deptRdr["Name"]);
SqlCommand cmd2 = conn.CreateCommand();
cmd2.CommandText = "SELECT * FROM Emp WHERE DeptID = " + dept_id;
SqlDataReader empReader = cmd2.ExecuteReader();
while (empReader.Read())
{
Console.WriteLine("\t{0} ({1})", empReader["Name"], empReader["EmpID"]);
}
empReader.Close();
}
deptRdr.Close();
conn.Close();
}