暇なのでつっついてみた。
DBはSQL Server 2005 Expressを使って適当に下みたいなのを作ってみた。
データベース名はEmpMngっていう名前にした。
create table Departments (
ID int IDENTITY(1,1) primary key,
Name nvarchar(100) not null);
create table Employees(
ID int IDENTITY(1,1) primary key,
Name nvarchar(100) not null,
Salary int not null,
DeptID int not null,
constraint FK_EMP_DEPT
foreign key(DeptID) references Departments(ID));
これにデータを入れてみようと思う。
その前に、昔hatenaに書いた時に使ったsqlmetalというコマンドじゃなくてVisual Studioの機能を使ってみた。
まず、新規作成からLINQ to SQLファイルを選んで、名前をEmpMngDataClassesにして追加を押す。
↑のほうで作ったデータベースへの接続を追加して、テーブルからEmployeesとDepartmentsをドラッグアンドドロップすると、下みたいな感じになる。
これで、EmpMngDataContextやらEmployeesやらDepartmentsのクラスが完成したっぽい。
プロパティとかをよく見てみると、EmployeesとDepartmentsのID列はDBで生成するよ~とかいった情報までちゃんと汲み取ってくれている。
ありがたいもんだ。
DBが空なんでDBにデータを突っ込んでみる。DBにデータを突っ込むためのコードはコレ。
TransactionScopeを使うので、Sysetm.Transactionsも参照に追加しとく。
using (EmpMngDataClassesDataContext ctx = new EmpMngDataClassesDataContext(
Settings.Default.EmpMngConnectionString))
using (TransactionScope tx = new TransactionScope())
{
ctx.Log = Console.Out; // SQL確認用
ctx.Departments.AddAll(new[] {
new Departments{ Name = "情報システム部" },
new Departments{ Name = "人事部" }});
ctx.SubmitChanges();
var depts = (from dept in ctx.Departments
orderby dept.ID
select dept).ToList();
ctx.Employees.AddAll(new[] {
new Employees{ Name = "一郎", Departments = depts[0] },
new Employees{ Name = "二郎", Departments = depts[0] },
new Employees{ Name = "三郎", Departments = depts[1] }});
ctx.SubmitChanges();
tx.Complete();
}
実行してみるとINSERT文等がもろもろ発行されているのがわかる。
データ追加の流れは、~~~DataContextを作ってAddする。SubmitChangesを呼ぶことでSQLをDBに発行する。
って感じでいけるっぽい。
さて、Employeesのデータを登録したけど給料を設定するのを忘れてた。
ってことで全員の給料を一律20万に更新するコードを書いてみた。
多分こんな感じでいける。
using (EmpMngDataClassesDataContext ctx = new EmpMngDataClassesDataContext(
Settings.Default.EmpMngConnectionString))
using (TransactionScope tx = new TransactionScope())
{
ctx.Log = Console.Out;
var emps = from emp in ctx.Employees
select emp;
foreach (var emp in emps)
{
emp.Salary = 200000;
}
ctx.SubmitChanges();
tx.Complete();
}
これを実行すると下のようなSQL文が発行されてた。
SELECT [t0].[ID], [t0].[Name], [t0].[Salary], [t0].[DeptID]
FROM [dbo].[Employees] AS [t0]
-- Context: SqlProvider(Sql2005) Model: AttributedMetaModel Build: 3.5.20706.1
UPDATE [dbo].[Employees]
SET [Salary] = @p4
WHERE ([ID] = @p0) AND ([Name] = @p1) AND ([Salary] = @p2) AND ([DeptID] = @p3)
-- @p0: Input Int32 (Size = 0; Prec = 0; Scale = 0) [1]
-- @p1: Input String (Size = 2; Prec = 0; Scale = 0) [一郎]
-- @p2: Input Int32 (Size = 0; Prec = 0; Scale = 0) [0]
-- @p3: Input Int32 (Size = 0; Prec = 0; Scale = 0) [1]
-- @p4: Input Int32 (Size = 0; Prec = 0; Scale = 0) [200000]
-- Context: SqlProvider(Sql2005) Model: AttributedMetaModel Build: 3.5.20706.1
以下略...
UPDATE文のWHERE句が、全カラム比較になってる。効率とかを気にするならもう一手間加えてあげないと駄目っぽい。
EmpMngDataClasses.dbmlファイルあたりを見てみるとそれっぽいプロパティとかもあるんで多分そう難しくなさそう。
次に、DBの中身を軽く表示してみるために、下のようなプログラムを書いて実行してみた。
using (EmpMngDataClassesDataContext ctx = new EmpMngDataClassesDataContext(
Settings.Default.EmpMngConnectionString))
{
var emps = from emp in ctx.Employees
orderby emp.ID
select new { emp.ID, emp.Name, DeptName = emp.Departments.Name };
foreach (var emp in emps)
{
Console.WriteLine(emp);
}
}
実行結果は↓
{ ID = 1, Name = 一郎, DeptName = 情報システム部 }
{ ID = 2, Name = 二郎, DeptName = 情報システム部 }
{ ID = 3, Name = 三郎, DeptName = 人事部 }
ちゃんと意図したとおりのデータが入ってた。
?
最後に!DBの中身を消してみる。こんな感じでいけるっぽい。
using (EmpMngDataClassesDataContext ctx = new EmpMngDataClassesDataContext(
Settings.Default.EmpMngConnectionString))
using (TransactionScope tx = new TransactionScope())
{
ctx.Log = Console.Out;
ctx.Employees.RemoveAll(from emp in ctx.Employees select emp);
ctx.Departments.RemoveAll(from dept in ctx.Departments select dept);
ctx.SubmitChanges();
tx.Complete();
}
このときに発行されるDELETE文もUPDATE文の時と同じで、WHERE句に全カラムぶんの比較がかかれてた。
JavaのHibernateやJPAみたいな動きをするので、Java組の人には馴染みやすいかも?