Linq to SQL にて複数行を DELETE
簡単な方法はありませんか? ADO.NET EF だと良い方法はありますか?
context.Table1.DeleteAllOnSubmit( from t1 in context.Table1 where t1.Key1 == value select t1);
やったことある人も、やったことなくても挙動が想像できる人もいると思うけど、非常に効率が悪いことになっちゃうんですよね。
良い子は、素直にストアドプロシージャにしましょう。
とりあえず、
var q = from t1 in context.Table1 where t1.Key1 == value select t1;
に対して、q.Count() とすれば SELECT COUNT() FROM... WHERE... が発行されるように、DELETE FROM... WHERE... が発行できれば文句ないんだが、単純にはいかない。というわけで最終手段の文字列操作にて、
private static Regex regex = new Regex( @"\bSELECT\b.+?\bFROM\b(?<TableSource>.+?(?<SourceAlias> AS .+?))\bWHERE\b", RegexOptions.Singleline); public static int DeleteAllOnImmediate<TEntity>(this DataContext context, IQueryable<TEntity> query) { Debug.Assert(context != null); Debug.Assert(query != null); using (var cmd = context.GetCommand(query)) { string sql = regex.Replace(cmd.CommandText, m => { string source = m.Groups["TableSource"].Value; string alias = m.Groups["SourceAlias"].Value; string table = source.Substring(0, source.Length - alias.Length); return "DELETE " + table + " FROM " + source + " WHERE"; }, 1); object[] parameters = new object[cmd.Parameters.Count]; for (int i = 0; i < parameters.Length; i++) parameters[i] = cmd.Parameters[i].Value; return context.ExecuteCommand(sql, parameters); } }
最初は DbCommand をまったく用いずに、IQueryable の ToString() メソッドから SQL を引っ張って、Expression プロパティと ExpressionVisitor を使ってパラメータを構築していた*1んだけど、ToString() を呼び出すのが嫌だったから DbCommand 経由に書き換え…。
良い子は、素直にストアドプロシージャにしましょう。*2