説明の中に出てくるテーブルはここのと同じです。
パラメータによって動的にSQLのwhere句を組み立てるっていう処理は、割とありがちだと思う。
今までなら、文字列だったんでいかようにでも組み立てることが出来たけど…
LINQだと無理じゃね?って感じになる。
たとえばこういうとき…
IEnumerable<Employees> Search(string name, int? minSalary, int? maxSalary)
{
// パラメータでnullじゃないヤツだけ検索条件に入れて欲しい
}
どうしましょう?ってことになる。
とりあえずLINQのwhere句の可読性を若干犠牲にしてこんな風に逃げることができる。
private static IEnumerable<Employees> Search(string name, int? minSalary, int? maxSalary)
{
using (var ctx = new EduDataContext(
Settings.Default.EmpMngConnectionString))
{
ctx.Log = Console.Out;
// Employesと一緒にDepartmentsも読み込んでね
DataLoadOptions ops = new DataLoadOptions();
ops.LoadWith<Employees>(e => e.Departments);
ctx.LoadOptions = ops;
return (from emp in ctx.Employees
where (name == null || emp.Name.Contains(name)) &&
(minSalary == null || minSalary <= emp.Salary) &&
(maxSalary == null || maxSalary >= emp.Salary)
select emp).ToArray();
}
}
nullが渡されたら、そこのパラメタの検索はtrueになるように仕込みを入れる。
こうしておくと不思議な事に、発行されるSQLからはnullの部分の検索条件がWHERE句からはずされてしまう。
たとえば、Search("太郎", 200000, null)と呼び出した場合のSQLはこんな感じ。
SELECT [t0].[ID], [t0].[Name], [t0].[Salary], [t0].[DeptID], [t0].[Version], [t1].[ID] AS [ID2], [t1].[Name] AS [Name2], [t1].[Version] AS [Version2]
FROM [dbo].[Employees] AS [t0]
INNER JOIN [dbo].[Departments] AS [t1] ON [t1].[ID] = [t0].[DeptID]
WHERE ([t0].[Name] LIKE @p0) AND (@p1 <= [t0].[Salary])
-- @p0: Input String (Size = 4; Prec = 0; Scale = 0) [%太郎%]
-- @p1: Input Int32 (Size = 0; Prec = 0; Scale = 0) [200000]
-- Context: SqlProvider(Sql2005) Model: AttributedMetaModel Build: 3.5.20706.1
maxSalaryの部分が綺麗になくなってる。賢い…。
もっと凝った感じのクエリを動的に組み立てたいときは、おとなしくSQLを発行するんだろうなぁ。
多分そのためのDataContext#ExecuteQuery<TResult>なんだろう。