追加の処理とは、標準の LINQ to SQL から Transact SQL への変換 (および可能な回避策) に加えて、
何も見つからないため、より多くの情報を見つけるために使用する洞察および/または適切なリンクまたはGoogle用語についての洞察を望んでいた2つの問題があります。要するに、実行される IQueryable 式が、式の結果の一部を「クライアント側」で実行する必要があることをいつ/どのように判断するかを知りたいということです。つまり、LINQ 式を直接変換することはできません。 Transact SQL に接続して、結果全体を返します。
これは私の投稿/コードに関するものです。
状況 1
string.Format()
Transact SQL には変換されません。私はそれを受け入れることができますが、式が Transact SQL に完全に変換できるかどうかを検出する方法についてのアドバイスを探していたと思います。
LINQ 式:
from h in HistoryData
select new { NewData = string.Format( "New Data: {0}", h.hisData ) };
プロバイダー コンテキスト SQL:
SELECT [t0].[hisData] AS [arg0]
FROM [HistoryData] AS [t0]
私の回避策: 現在、DataContext.GetCommand()
メソッドを使用してから、Transact SQL を調べて を検索してい[arg0]
ます。明らかに理想的ではないので、より堅牢なメカニズムを探していました (おそらく、ExpressionTree ビジターで何かを見つけられるでしょうか??)。
状況 2
いくつかの状況で三次演算子を使用すると、適切な値を取得するために明らかにポスト/クライアント処理が適用された Transact SQL が返されるようです。以下の例では、LINQPad のコンテキスト内で実行しています (したがって、Dump()
拡張メソッドが使用可能です)。三次演算子が使用されているときに後処理が必要になる状況は 2 つあります。
- ブール値フィールドとともにブール変数が使用されている場合 (以下の var testBool… 式) および
- タイプに関係なく 2 つの変数が使用され、データベース フィールドがクエリされない場合 (下の 2 番目の testNumber 式)。
この状況は、クライアント側の処理が必要であることに驚きました。したがって、通常の Transact SQL 以外で式を追加処理する必要がある場合を適切に検出する方法を学習することに加えて、他の状況のように L2S が単純な CASE ステートメントを実行できなかった理由と、さらに重要なこととして考えられる回避策について誰かが洞察を持っている場合「クライアント側」の処理を回避するために使用できます。
LINQ 式:
var before9_1_2009 = DateTime.Today < new DateTime( 2009, 9, 1 );
var fiveThousand = 5000;
var tenThousand = 10000;
var testNumber =
Profiles.Where( p => p.pAuthID == "111111111" )
.Select( p => new { Number = before9_1_2009 ? fiveThousand : p.pKey } );
var cmd = GetCommand( testNumber );
cmd.CommandText.Dump( "Number Property: Works (i.e. evaluates on SQL Server)" );
var testString =
Profiles.Where( p => p.pAuthID == "111111111" )
.Select( p => new { String = before9_1_2009 ? "StringConstant" : p.pAuthID } );
cmd = GetCommand( testString );
cmd.CommandText.Dump( "String Property: Works (i.e. evaluates on SQL Server)" );
var testBool =
Profiles.Where( p => p.pAuthID == "111111111" )
.Select( p => new { Boolean = boolExp ? true : p.pProcessed } );
cmd = GetCommand( testBool );
cmd.CommandText.Dump( "Boolean Property: Has NULL AS [EMPTY] - Post Processing Needed" );
testNumber =
Profiles.Where( p => p.pAuthID == "111111111" )
.Select( p => new { Number = before9_1_2009 ? fiveThousand : tenThousand } );
cmd = GetCommand( testNumber );
cmd.CommandText.Dump( "Number Property (using two constants): Has NULL AS [EMPTY] - Post Processing Needed" );
プロバイダー コンテキスト SQL (順番): ▪ 数値プロパティ: 機能します (つまり、SQL Server で評価されます)。
SELECT
(CASE
WHEN @p1 = 1 THEN @p2
ELSE [t0].[pKey]
END) AS [Number]
FROM [Profile] AS [t0]
WHERE [t0].[pAuthID] = @p0
▪ 文字列プロパティ: 動作します (つまり、SQL Server で評価されます)。
SELECT
(CASE
WHEN @p1 = 1 THEN CONVERT(NVarChar(255),@p2)
ELSE [t0].[pAuthID]
END) AS [String]
FROM [Profile] AS [t0]
WHERE [t0].[pAuthID] = @p0
▪ Boolean プロパティ: Has NULL AS [EMPTY]
SELECT NULL AS [EMPTY]
FROM [Profile] AS [t0]
WHERE [t0].[pAuthID] = @p0
▪ Number プロパティ (2 つの定数を使用): Has NULL AS [EMPTY]
SELECT NULL AS [EMPTY]
FROM [Profile] AS [t0]
WHERE [t0].[pAuthID] = @p0
私の回避策: 繰り返しますが、DataContext.GetCommand()
メソッドを使用してから、Transact SQL を調べてNULL AS [EMPTY]
. サーバー上で実行できない式コードに対して表示される「魔法の文字列」が他にないかどうか疑問に思っています...上記のように、これらの状況を検出するための正確でより堅牢な方法を探しています。