Entity Frameworkの不便なところ
バージョン番号の自動インクリメント
楽観的排他制御のためにWHERE句に特定のカラムを条件として入れる機能はありますが、「バージョン番号」という考え方がないんですね。したがって、バージョン番号を自動でインクリメントする機能もありません。
これは不便なのでSomaで対応しようと思います。
使う側は、バージョン番号を意識することなく普通に更新処理を行います(CSDLにConcurrencyMode="Fixed"を設定しておく必要はあります)。
var employeeRepository = new EmployeeRepository(); var employee = employeeRepository.SelectById(1); Console.WriteLine(employee.VersionNo); // 0 employee.EmployeeName = "hoge"; employeeRepository.Update(employee); Console.WriteLine(employee.VersionNo); // 1
発行されるSQLはこうなります。
update [dbo].[Employee] set [EmployeeName] = 'hoge', [VersionNo] = 1, [DepartmentId] = 1 where (([EmployeeId] = 1) and ([VersionNo] = 0))
set句に指定されるVersionNoの値が0から1にインクリメントされています。
オブジェクトコンテキストからのデタッチ
Entity Frameworkって、オブジェクトコンテキストを閉じてもエンティティを自動でデタッチしてくれないんですよね。たとえば標準のAPIで更新したときのエンティティの状態を見てみます。
Employee emp = null; using (var context = new SampleEntities()) { emp = context.Employee.Single(e => e.EmployeeId == 1); emp.EmployeeName = "hoge"; context.SaveChanges(); } Console.WriteLine(emp.EntityState); // Unchanged
この例だと状態はUnchangedになっていますが、直感的にはcontextが閉じられたら紐つくエンティティの状態は全部Detachedになるのがわかりやすいと思うんです。Detachedにならないと、関連オブジェクトを辿ったときに遅延ローディングしようとしてエラーになったりするんですよね。
Somaでは、オブジェクトコンテキストを閉じる直前ですべてのエンティティを自動でデタッチしようと思います。つまり、SomaのRepositoryから返されるエンティティはすべてDetachedな状態になる予定です。