2014-02-25 4 views
2

조건부 "? :"연산자가 포함 된 LINQ-to-SQL 쿼리를 컴파일해야합니다. 그런 쿼리를 컴파일 할 수는 있지만 문제는 실행하려고 할 때 실패한다는 것입니다.조건부 연산자가 포함 된 LINQ to SQL 컴파일 된 쿼리를 실행하는 방법?

MyContext myContext = new MyContext(sqlConnection); 
myContext.Log = Console.Out; 

var cq = CompiledQuery.Compile(
     (MyContext context, bool option) => 
       option ? context.GetTable<User>().Where(x => x.UserId > 5) 
         : context.GetTable<User>().Where(x => x.UserId < 5)); 

//Crashes when trying to invoke. 
cq.Invoke(myContext, true); 

콘솔 출력이 예상 SQL 문이 실행 된 보여줍니다 :

SELECT [t0].[UserId],... 
FROM [dbo].[User] AS [t0] 
WHERE [t0].[UserId] > @p0 
-- @p0: Input Int (Size = -1; Prec = 0; Scale = 0) [5] 

그러나이 결과 세트를 열거하는 동안 실행이 실패 나타납니다 여기에

간단한 생식입니다 데이터베이스

"시퀀스에 둘 이상의 요소가 포함되어 있습니다"라는 메시지가있는 InvalidOperationException은 예외입니다.

스택 추적은 다음과 같습니다

at System.Linq.Enumerable.SingleOrDefault[TSource](IEnumerable`1 source) 
at Read_User(ObjectMaterializer`1) 
at System.Data.Linq.SqlClient.ObjectReaderCompiler.ObjectReader`2.MoveNext() 
at Program.Main() ... 

사람이 실행할 수있는 방법을 제공 할 수 있습니까? 내가 들어갈 수없는 이유로이 조건부 논리를 표현식 외부로 옮길 수는 없으며 컴파일 된 쿼리의 일부 여야합니다.

+0

아마도 버그 일 수 있습니다. 버그는 여러 쿼리 사이를 런타임으로 전환 할 수 없다는 오류를주지 않는다는 것입니다. 그들은 아마도'CompiledQuery.Compile'의 사용법을 결코 의도하지 않았습니다. – usr

+0

예, 그게 제가 두려워하는 것입니다. 그러나 SQL 문이 올바르게 실행되기 때문에이 작업을 수행 할 수있는 가능성이 있다고 생각했습니다. –

+1

두 개의 쿼리 또는'UserId> = (옵션? 0 : 5) && UserId <(옵션? 5 : int.MaxValue)'를 컴파일하십시오. 이 술어는 여전히 SARGable입니다. – usr

답변

1

아마도 버그입니다. 버그는 여러 쿼리 사이를 런타임으로 전환 할 수 없다는 오류를주지 않는다는 것입니다. 그들은 아마도 CompiledQuery.Compile의 사용을 의도하지 않았습니다.

두 개의 쿼리 또는 : UserId >= (option ? 0 : 5) && UserId < (option ? 5 : int.MaxValue)을 컴파일하십시오. 이 술어는 여전히 SARGable입니다.