DLinqを試す - かずきのBlog@Hatenaの続きだよ。
この間のテーブルにありがちなリレーションをつけてみたよ。
Departmentsテーブルを追加してみたよ。
そして、EmployeesテーブルにはDeptIDっていうカラムを付け足してDepartmentsテーブルに対して外部キーを張ってみたよ。
テストデータはこんな感じで用意してみたよ。
Employeesテーブル
ID | Name | DeptID |
1 | 太郎 | 1 |
2 | 二郎 | 1 |
3 | 三郎 | 2 |
4 | 四郎 | 2 |
5 | 五郎 | 3 |
Departmentsテーブル
ID | Name |
1 | 総務部 |
2 | 人事部 |
3 | 情報システム部 |
前回と同じ要領でsqlmetalコマンドで必要なクラスを自動生成してみるね。
そして実験コードを書いてみたよ。
EDU edu = new EDU(@"Server=KAZUKI-PC\SQLEXPRESS;Database=EDU;Integrated Security=true"); edu.Log = Console.Out; var emps = from emp in edu.Employees where emp.ID == 1 select emp; foreach (var emp in emps) { Console.WriteLine("Name = {0}", emp.Name); Console.WriteLine("DeptName = {0}", emp.Departments.Name); }
何のことはない、太郎君の名前と部署名を表示するだけだね。
実行してみるよ。
SELECT [t0].[ID], [t0].[Name], [t0].[DeptID] FROM [Employees] AS [t0] WHERE [t0].[ID] = @p0 -- @p0: Input Decimal (Size = 0; Prec = 29; Scale = 4) NOT NULL [1] SqlProvider\AttributedMetaModel Name = 太郎 SELECT [t0].[ID], [t0].[Name] FROM [Departments] AS [t0] WHERE [t0].[ID] = @p0 -- @p0: Input Decimal (Size = 0; Prec = 29; Scale = 4) NOT NULL [1] SqlProvider\AttributedMetaModel DeptName = 総務部
ログを標準出力に出すようにしてるからちょっとSQL文が邪魔だけど、よく見るとわかるよね?
プログラム中で、emp.Departmentsに初めてアクセスしたタイミングでDepartmentsテーブルに対してのSQL文が発行されているね。
Hibernateを思い出すような動きをしてるよ。
ここで、明示的に一気にDepartmentsテーブルのデータも最初のクエリでとってきたい!というときにはどうするんだろう?
Hibernateでは、明示的にJOINすればよかったから試してみたよ。
EDU edu = new EDU(@"Server=KAZUKI-PC\SQLEXPRESS;Database=EDU;Integrated Security=true"); edu.Log = Console.Out; var emps = from emp in edu.Employees join dept in edu.Departments on emp.DeptID equals dept.ID where emp.ID == 1 select emp; foreach (var emp in emps) { Console.WriteLine("Name = {0}", emp.Name); Console.WriteLine("DeptName = {0}", emp.Departments.Name); }
実行してみるよ。
SELECT [t0].[ID], [t0].[Name], [t0].[DeptID] FROM [Employees] AS [t0], [Departments] AS [t1] WHERE ([t0].[ID] = @p0) AND ([t0].[DeptID] = [t1].[ID]) -- @p0: Input Decimal (Size = 0; Prec = 29; Scale = 4) NOT NULL [1] SqlProvider\AttributedMetaModel Name = 太郎 SELECT [t0].[ID], [t0].[Name] FROM [Departments] AS [t0] WHERE [t0].[ID] = @p0 -- @p0: Input Decimal (Size = 0; Prec = 29; Scale = 4) NOT NULL [1] SqlProvider\AttributedMetaModel DeptName = 総務部
残念な事にSQLが2つ発行されちゃった…
これはこういうものだと思ってあきらめるしかないのかな?
もしくは、ほしいデータだけ匿名クラスで返してもらうようにするか。
下みたいな感じにね。
EDU edu = new EDU(@"Server=KAZUKI-PC\SQLEXPRESS;Database=EDU;Integrated Security=true"); edu.Log = Console.Out; var emps = from emp in edu.Employees where emp.ID == 1 select new { Name = emp.Name, DeptName = emp.Departments.Name } ; foreach (var emp in emps) { Console.WriteLine("Name = {0}", emp.Name); Console.WriteLine("DeptName = {0}", emp.DeptName); }
実行結果を見るとSQLが1つだけになってるのが分かると思うよ。
SELECT [t0].[Name], [t1].[Name] AS [Name2] FROM [Employees] AS [t0], [Departments] AS [t1] WHERE ([t1].[ID] = [t0].[DeptID]) AND ([t0].[ID] = @p0) -- @p0: Input Decimal (Size = 0; Prec = 29; Scale = 4) NOT NULL [1] SqlProvider\AttributedMetaModel Name = ほげほげ DeptName = 総務部
当然といえば当然の結果だよね。