SQL Serverに限らず、DB接続時にやってはいけない事として、「DB関連オブジェクトの共有」という物があります。
ちょっと纏まって無いですが、後で例に挙げるコードだとこんな例外がでます。
- $exception {"操作が無効です。接続は閉じています。"} System.Exception {System.InvalidOperationException}
- $exception {"接続が閉じられていません。現在の接続の状態は '接続中\" です。。"} System.Exception {System.InvalidOperationException}
- $exception {"ExecuteReader は、コマンドに割り当てられた接続が保留状態であるローカルのトランザクションにあるとき、トランザクション オブジェクトを持つコマンドが必要です。コマンドの Transaction プロパティがまだ初期化されていません。"} System.Exception {System.InvalidOperationException}
- $exception {"SubmitChanges の呼び出し中は、その操作を実行できません。"} System.Exception {System.InvalidOperationException}
例外方の言ってる事としては、「DBに接続するオブジェクトを共有してるんじゃねーよ、トランザクションつくれねぇだろう」という事の様です。
もちっとまとめないと…orz
コード例
やっている事は以下の二つです。
- 共通のDBオブジェクトを作成
- 並列実行用のオブジェクト作成
で、上の二つをとりあえず実行してみた感じ。
class InfoDto { public string Name { get; set; } public int SleepTime { get; set; } } class Program { static void Main(string[] args) { string connection = ConfigurationManager.ConnectionStrings["DotNetSampleDBConnectionString"].ConnectionString; DataClasses1DataContext dataContext = new DataClasses1DataContext(connection); dataContext.Log = Console.Out; dataContext.CommandTimeout = 1; //並列実行用の関数作成 WaitCallback func = delegate(object obj) { InfoDto infoDto = obj as InfoDto; Console.WriteLine("db access start: {0}, sleep={1}", infoDto.Name, infoDto.SleepTime); Thread.Sleep(infoDto.SleepTime); dataContext.SampleTable1.First().COMMENT = infoDto.Name + " がupdate したよー"; dataContext.SubmitChanges(); Console.WriteLine("db access finish: {0}, sleep={1}", infoDto.Name, infoDto.SleepTime); }; List<WaitHandle> waitHandles = new List<WaitHandle>(); waitHandles.Add(func.BeginInvoke(new InfoDto { Name = "No.1", SleepTime = 300 }, null, null).AsyncWaitHandle); waitHandles.Add(func.BeginInvoke(new InfoDto { Name = "No.2", SleepTime = 2500 }, null, null).AsyncWaitHandle); waitHandles.Add(func.BeginInvoke(new InfoDto { Name = "No.3", SleepTime = 3500 }, null, null).AsyncWaitHandle); waitHandles.Add(func.BeginInvoke(new InfoDto { Name = "No.4", SleepTime = 1500 }, null, null).AsyncWaitHandle); //ここでまとめて実行 WaitHandle.WaitAll(waitHandles.ToArray()); Console.WriteLine("------------ end ------------"); Console.ReadLine(); } }