현재 카테고리에 맞지 않는 영역이지만....
관리도 안될게 뻔한 카테고리를 새로 만들고 싶지 않아 ASP.NET MVC 카테고리에 꺼적인다
ASP.NET MVC로 DB 관련 개발할 때,
EntityFramework 나 LING to SQL을 사용하곤 한다
근데 이 두 넘은 다 좋은데, 저장 프로시저의 다중 결과 셋을 지원하지 않는다.
음.. 지원하지 않는다기 보다는 자동으로 생성되는 designer.cs에만 의존하면 그렇다고 해야 정확한 표현인 듯 싶다.
예를 들어,
게시판 글 보기 페이지일 경우, 글 내용과 해당 글에 대한 댓글 정보를 하나의 프로시저에서 두 개의 결과 셋으로 반환하도록 할 경우 처음으로 반환된 결과 셋이 자동으로 바인딩 되는 것이다
물론 이런 상황이라면 글 내용은 OUTPUT 변수로 받고 댓글 리스트는 결과셋으로 받아서 해결 가능하다. 실제로 이렇게 사용한 적이 꽤 많다.
그러나 문제는 정말로 리스트형태의 결과 셋이 여러 개일 경우이다. 이젠 더 이상 OUTPUT 반환 값에 의존할 수 없게 되었다.
저장프로시저의 시나리오는 대략 이렇다.
1. OUTPUT 변수로 몇 가지 값을 반환한다
2. 3개의 결과 셋(레코드 셋이라는 표현을 좋아하는 사람이 있다)도 같이 반환한다
그러니깐, 의미적으로 총 3가지 형태의 결과값을 받고 싶은 게다
(OUTPUT 반환 값 + 결과셋1 + 결과셋2 + 결과셋3)
물론 결과셋의 개수는 중요치 않다. 두 개 이상의 결과셋을 반환한다는 게 중요하다
이제 이 프로시저를 LINK to SQL로 연동해서 결과를 처리하고 싶다
먼저 desiner.cs 가 자동 생성한 아래의 코드를 보자
[global::System.Data.Linq.Mapping.FunctionAttribute(Name="dbo.USP_GetGameView")]
public ISingleResult<USP_GetGameViewResult> USP_GetGameView([global::System.Data.Linq.Mapping.ParameterAttribute(Name="GameNo", DbType="SmallInt")] System.Nullable<short> gameNo, [global::System.Data.Linq.Mapping.ParameterAttribute(Name="GameName", DbType="NVarChar(100)")] ref string gameName, [global::System.Data.Linq.Mapping.ParameterAttribute(Name="Score", DbType="Decimal(2,1)")] ref System.Nullable<decimal> score, [global::System.Data.Linq.Mapping.ParameterAttribute(Name="Description", DbType="NVarChar(400)")] ref string description)
{
IExecuteResult result = this.ExecuteMethodCall(this, ((MethodInfo)(MethodInfo.GetCurrentMethod())), gameNo, gameName, score, description);
gameName = ((string)(result.GetParameterValue(1)));
score = ((System.Nullable<decimal>)(result.GetParameterValue(2)));
description = ((string)(result.GetParameterValue(3)));
return ((ISingleResult<USP_GetGameViewResult>)(result.ReturnValue));
}
매우 복잡한(?) 코드에 의미 두지 말자. designer.cs 가 자동 생성해 준 코드를 그대로 옮긴 것이니..
그리고 저장프로시저의 원형에 의미도 두지 말자. 그냥 대충 다중 셋을 반환하는 저장프로시저라고 생각하면 된다. 중요한 것은 ISingleResult를 반환한다는 점이다. 그래서 다중 결과 셋의 첫 번째 결과만 바인딩 되는 것이다.
그렇다면 해결책은 ISingleResult가 아닌 다중 셋을 반환할 수 있도록 IMultipleResults을 반환하면 된다.
이를 위한 새로운 메서드를 정의해야 하는 데, designer.cs가 자동 생성한 클래스를 사용할 생각은 말아야 한다. DB 연동이 추가/제거/변경 될 경우 이 클래스는 다시 생성되기 때문에 자신의 코드가 모두 사라질 수 있기 때문이다.
그렇기 때문에 파티셜 클래스 기법을 이용하면 된다.
designer.cs가 생성한 클래스와 동일한 이름으로 파티셜 클래스를 선언하고 다중 셋을 반환할 수 있도록 다음과 같이 작성할 수 있다
{
[Function(Name = "dbo.USP_GetGameView")]
[ResultType(typeof(ScreenShot))]
[ResultType(typeof(Video))]
[ResultType(typeof(CommentInfo))]
public IMultipleResults GetGameView(short? gameNo, ref string gameName, ref decimal? score, ref string description)
{
IExecuteResult result = this.ExecuteMethodCall(this, ((MethodInfo)(MethodInfo.GetCurrentMethod())), gameNo, gameName, score, description);
gameName = ((string)(result.GetParameterValue(1)));
score = ((System.Nullable<decimal>)(result.GetParameterValue(2)));
description = ((string)(result.GetParameterValue(3)));
return (IMultipleResults) result.ReturnValue;
}
}
자동생성된 이전의 코드와 거의 유사한 것을 알 수 있다
다른 점이라면 IMultipleResults 타입을 반환한다는 점과, 다중 셋의 결과를 자동으로 바인딩 하기 위한 클래스 선언이 있다는 점이다.
LINQ to SQL을 사용하면서 다중 결과 셋에 대한 목마름이 있었던 사람은 위의 코드만으로도 그 즉시 적용가능하리라 본다.
'.NET Framework' 카테고리의 다른 글
Generic DataContract in WCF (0) | 2013.05.09 |
---|---|
WCF Data Service VS ASP.NET Web API (2) | 2013.01.08 |
MVC 다중 폼 유효성 체크 (0) | 2012.09.07 |
Razor 구문 (0) | 2011.07.19 |
ASP.NET Razor (5) | 2010.12.13 |