LINQ to SQL で追加、更新、削除

Visual Studion 2008 の Express Editionでいろいろと動かしてみました。DBのスキーマはよくある、Department、Employeeで。DepartmentとEmployeeは1対多でEmployeeがDepartmentに対する外部キーを持っています。エンティティのコードはVisualStudioで自動生成したものを使います。

本当は、テストコードで確かめられるといいんだけど、Express EditionにNUnitとか入れるのはしんどそうだったので、次のようなコードで実行することにしました。

class Program
{
    private StudyDataContext db; // 自動生成したDataContextのサブクラス

    static void Main(string[] args)
    {
        using (TransactionScope ts = new TransactionScope()) 
        {
            using (StudyDataContext db = new StudyDataContext())
            {
                Program program = new Program();
                db.Log = Console.Out;
                program.db = db;
                program.xxx(); // 面倒くさいけど、呼び出すメソッドを変更して実行
            }
        }
        Console.ReadLine();
    }
}

追加(INSERT文の発行)

InsertOnSubmitメソッドで追加

もっともオーソドックスなもの。SubmitChangesを呼ばないとSQLは発行されないです。

void InsertOnSubmitメソッドで追加()
{
    Employee e = new Employee { EmployeeId = 20, EmployeeNo = 1000, EmployeeName = "hoge" };
    db.Employee.InsertOnSubmit(e);

    db.SubmitChanges();
}
関連の操作で追加その1

関連先にAddしてもOK。ちなみに Single(x => x.DepartmentId == 1) というコードはDepartmentIdが1のものを1件だけ取得するメソッドです。複数件が返される場合はエラーになります。

void 関連の操作で追加その1()
{            
    Department d = db.Department.Single(x => x.DepartmentId == 1);
    Employee e = new Employee { EmployeeId = 20, EmployeeNo = 1000, EmployeeName = "hoge" };
    d.Employee.Add(e);
        
    db.SubmitChanges();
}
関連の操作で追加その2

関連の操作で追加その1では、DepartmentにEmployeeをAddしていましたが、ここではEmployeeにDepartmentをセットしています。どちらでも同じ結果になります。

void 関連の操作で追加その2()
{
    Department d = db.Department.Single(x => x.DepartmentId == 1);
    Employee e = new Employee { EmployeeId = 20, EmployeeNo = 1000, EmployeeName = "hoge" };
    e.Department = d; 

    db.SubmitChanges();
}
ExecuteCommandメソッドで追加

直接SQLの実行もできます。

void ExecuteCommandメソッドで追加()
{
    db.ExecuteCommand(
        @"insert into Employee (EmployeeId, EmployeeNo, EmployeeName) values ({0}, {1}, {2})", 
        20, 1000, "hoge");
}

削除(DELETE文の発行)

DeleteOnSubmitメソッドで削除

オーソドックスなのもの。

void DeleteOnSubmitメソッドで削除()
{
    var e = db.Employee.Single(x => x.EmployeeId == 1);
    db.Employee.DeleteOnSubmit(e);

    db.SubmitChanges();
}
ExecuteCommandメソッドで削除

SQLで直接もOK。

void ExecuteCommandメソッドで削除()
{
    db.ExecuteCommand(
        @"delete from Employee where EmployeeId = {0}", 
        1);
}

削除は、関連の操作ではできないです。関連先からRemoveしたりするとDELETEされるのかと思いきや、それはサポートしていなくて、SQLとしてはUPDATE文が発行されることになるので更新のところでで扱います。

更新(UPDATE文の発行)

状態の変更で更新

エンティティのプロパティを変更すれば更新対象になります。JPAっぽいですね。ただし、自動でフラッシュはされないのでちゃんとSubmitChangesを呼んであげる必要があります。ちなみに、更新されるのは変更したプロパティだけです。

void 状態の変更で更新()
{
    var e = db.Employee.Single(x => x.EmployeeId == 1);
    e.EmployeeName = "hoge";

    db.SubmitChanges();
}
関連の操作で更新その1

関連先からRemoveしていますが、EmployeeからDepartmentへの外部キーがnullになるようにUPDATE文が発行されます。外部キーにNOT NULL制約をつけている場合、この操作は例外になります。

void 関連の操作で更新その1()
{
    var d = db.Department.Single(x => x.DepartmentId == 1);
    var e = d.Employee.First();
    d.Employee.Remove(e);

    db.SubmitChanges();
}
関連の操作で更新その2

関連先へのプロパティをnullにセットしています。関連の操作で更新その1と同じように、EmployeeからDepartmentへの外部キーがnullになるようにUPDATE文が発行されます。

void 関連の操作で更新その2()
{
    var e = db.Employee.Single(x => x.EmployeeId == 1);
    e.Department = null;

    db.SubmitChanges();
}
関連の操作で更新その3

関連先にAddしていますが、外部キーを更新するUPDATE文が発行されます。

void 関連の操作で更新その3()
{
    var d = db.Department.Single(x => x.DepartmentId == 1);
    var e = d.Employee.First();
    var d2 = db.Department.Single(x => x.DepartmentId == 2);
    d2.Employee.Add(e);

    db.SubmitChanges();
}
関連の操作で更新その4

関連先へのプロパティを変更しています。関連の操作で更新その3と同じように、外部キーを更新するUPDATE文が発行されます。

void 関連の操作で更新その4()
{
    var d = db.Department.Single(x => x.DepartmentId == 1);
    var e = d.Employee.First();
    var d2 = db.Department.Single(x => x.DepartmentId == 2);
    e.Department = d2;

    db.SubmitChanges();
}
ExecuteCommandメソッドで更新

直接SQLの実行もできます。

void ExecuteCommandメソッドで更新()
{
    db.ExecuteCommand(
        @"update Employee set EmployeeNo = {0}, EmployeeName = {1} where EmployeeId = {2}", 
        20, "hoge", 1);
}