かるあ のメモ

アクセスカウンタ

help リーダーに追加 RSS LINQ と同時実行制御 その3

<<   作成日時 : 2007/10/12 11:10   >>

トラックバック 0 / コメント 0

前回の予告したように多層アプリケーション時に LINQ to SQL でコンフリクトをどのように捕捉するかを考えます。

まず LINQDataSource の部分をクラス化してあげます。
Web などのステートレスな処理を行う場合は LINQ to SQL の DataContext をリクエストの度に作成する必要があります。
検索と更新のコードはこんな感じでしょうか。
Public Class ComuplusUser
  ''' <summary>
  ''' ユーザの一覧を取得する。
  ''' </summary>
  Public Function GetUsers() As List(Of User)
    Using db = New こみゅぷらすDataContext()
      db.ObjectTrackingEnabled = False
      Return db.User.ToList()
    End Using
  End Function

  ''' <summary>
  ''' ユーザを更新する。
  ''' </summary>
  Public Sub UpdateUser(ByVal editUser As User)
    Using db = New こみゅぷらすDataContext()
      ' 更新対象のユーザを検索
      Dim targetUser = New User With { _
          .UserID = editUser.UserID, _
          .UpdateDate = editUser.UpdateDate _
      }
      db.User.Attach(targetUser)

      ' 更新情報を格納
      targetUser.UserName = editUser.UserName
      targetUser.PostNo = editUser.PostNo
      targetUser.PostSubNo = editUser.PostSubNo

      ' 更新を確定
      db.SubmitChanges()
    End Using
  End Sub
End Class

更新時の流れは次のようになります。
1.更新対象のレコードを検索
2.更新情報を格納
3.更新を確定

更新対象のレコードを Attach する前に更新情報を格納しても無視されるようです。
こうは書けない
Public Sub UpdateUser(ByVal editUser As User)
  Using db = New こみゅぷらすDataContext()
    db.User.Attach(editUser)
    db.SubmitChanges()
  End Using
End Sub

ページの方では LINQDataSource を Object DataSource に変更して、ObjectDataSource にクラス情報を設定します。
<asp:GridView ID="GridView1" runat="server"
   AutoGenerateColumns="False"
   DataSourceID="ObjectDataSource1"
   DataKeyNames="UserID, UpdateDate">
 <Columns>
  <asp:commandfield ShowEditButton="True">
  </asp:commandfield>
  <asp:boundfield DataField="UserID"
          HeaderText="UserID"
          ReadOnly="True"
          SortExpression="UserID">
  </asp:boundfield>
  <asp:boundfield DataField="UserName"
          HeaderText="UserName"
          SortExpression="UserName">
  </asp:boundfield>
 </Columns>
</asp:GridView>
<asp:ObjectDataSource ID="ObjectDataSource1"
           runat="server"
           DataObjectTypeName="User"
           SelectMethod="GetUsers"
           TypeName="ComuplusUser"
           UpdateMethod="UpdateUser">
</asp:ObjectDataSource></span


コンフリクトの検知は LINQDataSource と同様 ObjectDataSource の Updated イベントを捕捉し、 Exception を調べます。
ここで注意したいのが、ObjectDataSource の場合 ComuplusUserクラス側で ChangeConflictException が発生しても e.Exception に格納されているのは TargetInvocationException になってしまうので、サービス側で起きた例外を調べたいときは e.Exception.InnerException を調べる必要があるということです。

このあたりはライブラリ化した場合に .NET 3.5 以前から使われることを想定したらサービス側で LINQ の Exception を捕捉して当たり障りのないものに変更したほうがいいのかな?
それとも更新メソッドのインターフェイスを返却用のクラス経由でこんな風にして Updated 側で例外ではなく返却値を調査させた方がいいか。

サービス側
Public Class ServiceResult
    Public Status As Boolean
    Public Message As String
    Public InnerException As Exception
End ClassPublic Function UpdateUser(ByVal editUser As User) As ServiceResult

WebPage側
Protected Sub ObjectDataSource1_Updated(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.ObjectDataSourceStatusEventArgs) Handles ObjectDataSource1.Updated

  Dim result = DirectCast(e.ReturnValue, ServiceResult)
  If Not result.Status Then
    Label1.Text = Message
  End If
End Sub

設定テーマ

注目テーマ 一覧

月別リンク

トラックバック(0件)

タイトル (本文) ブログ名/日時

トラックバック用URL help


自分のブログにトラックバック記事作成(会員用) help

タイトル
本 文

コメント(0件)

内 容 ニックネーム/日時

コメントする help

ニックネーム
本 文