ぼくのつかっているLINQ to SQLのかくちょうめそっど

今更なんだけど、L2Sの更新系処理に関してちょっと。


LINQ to SQLって、参照系は良いんだけど、更新系は弱いよね〜というのが一般的な見解で(´Д`)
じゃあどうすんだよと言えば、そこは自前の拡張メソッドを用意したりで対処するわけですが(・∀・)


まあ、具体的な話は下記のあたりを参照して貰うとして。

http://weblogs.asp.net/jeffreyzhao/archive/2008/03/06/linq-to-sql-extension-batch-deletion-by-lambda-expression.aspx
http://www.aneyfamily.com/terryandann/post/2008/04/Batch-Updates-and-Deletes-with-LINQ-to-SQL.aspx

自分もそれらを参考にして、以下の様な更新系の拡張メソッドを用意することにより、LINQ to SQLの更新系の処理の弱さに対処しています。

// PKで削除
public static int DeleteByPK<T>(this Table<T> table, object primaryKey)

// 該当レコード削除
public static int DeleteBatch<T>(this Table<T> table, Expression<Func<T, bool>> filter)
public static int DeleteBatch<T>(this Table<T> table, IQueryable<T> query)

// PKで更新
public static int UpdateByPK<T>(this Table<T> table, object primaryKey, Expression<Func<T, T>> evaluator)

// 該当レコード更新
public static int UpdateBatch<T>(this Table<T> table, Expression<Func<T, bool>> filter, Expression<Func<T, T>> evaluator)
public static int UpdateBatch<T>(this Table<T> table, IQueryable<T> query, Expression<Func<T, T>> evaluator)
// 使用例

// PKで削除
int effect = context.Employee.DeleteByPk( 4054 );

// PK(Key1とKey2の2カラム)で削除
int effect = context.SampleTeble.DeleteByPk( new { Key1 = 10, Key2 = "ABC" } );

// PKで更新
int effect = context.Employee.
    UpdateByPK( 4054,
                c => new Employee()
                     {
                         Name = c.Name + "だよもん",
                     } );

// 該当レコード更新
int effect = context.Employee.
    UpdateBatch( c => c.Department.Id == 9999 && c.Rank = "S"
                 c => new Employee()
                      {
                          Enabled = false,
                          UpdatedAt = DateTime.Now,
                      } );

やっている事の概略ですが、テーブル名、PKなんかの情報はMetaTableを使って、そこからSQLを構築、DataContext.ExecuteQuery()という内容。
Batch系での条件指定については、Table.Context.GetCommand( query ).CommandTextで取得したSQLを元に、JOIN句を生成してそれを条件にして。
Update処理のExpression>については、MemberInitExpression、ParameterExpressionとかを評価してSET句の生成という感じで。


っで、これらの拡張メソッドにより、更新処理でも困らないようになっています(・∀・)
リソース系の操作が主体の場合にはこれで十分だし。
これらのメソッドで対処できない内容については、ストアドでの処理なんかを考えるしね。


これ、方向性としては賢いO/R Mappingというよりも、ベタなR/O Mappingな臭いがしますが(・ω・)
まあ、とりあえず自分が求めているのはそっちの方向なので。
オブジェクトのトラッキングはあまりいらない、デザイナ上での作業はしたくない、とかも。


っということで、.NET、Java、その他を含めたO/R Mapperの中で、自分が今のところ最も気に入っているがLINQ to SQLなわけですが、それはこれらの拡張メソッド込みでの話(・∀・)