4

私のアプリケーションには、異なるスキーマを持つ異なるデータベースに接続するいくつかの DataContexts があります。カスタム ユーザー コントロールでは、クエリの結果を表示し、ユーザーがそれらを編集できるようにします。ユーザーがデータを編集するときに、データベースへの変更を保持したいと考えています。そのためには、ソース DataContext (または少なくともソース datacontext タイプ) への参照が必要です。DataContext.SubmitChanges();

クエリがどの DataContext から来ているかを判断する方法はありますか? DataQuery クラス自体は内部としてマークされているため、醜いリフレクション ハックに頼らないとそのコンテキスト プロパティにアクセスできないため、よりクリーンなアプローチを探しています。

たとえば、ソース DataContext への参照を渡すことで、この問題を回避する (いくつかの) 方法がありますが、これを行うにはもっと簡単な方法が必要だと思います。

編集:次のコードは機能しますが、醜いです:

FieldInfo contextField = query.GetType().GetField("context", BindingFlags.Instance | BindingFlags.NonPublic);
if (query != null)
{
  queryContext = contextField.GetValue(value) as DataContext;
}
4

2 に答える 2

2

はい - リフレクションを使用することが、クエリが属する DataContext を特定する唯一の方法です。クエリがトリガーされたときに作成されるデータ オブジェクトと同じです。

以下はルーンの質問に厳密に答えるものではありませんが、リフレクションを使用して、データ オブジェクトがデータ コンテキストにアタッチされ、監視されているかどうかを判断する場合に役立つ場合があります。

次のコードは、データ オブジェクトに配置できる Context プロパティを定義し、オブジェクトがアタッチされている DataContext (存在する場合) を返すために使用します。

Private Const StandardChangeTrackerName As String = "System.Data.Linq.ChangeTracker+StandardChangeTracker"

Private _context As DataClasses1DataContext
Public Property Context() As DataClasses1DataContext
    Get
        Dim hasContext As Boolean = False
        Dim myType As Type = Me.GetType()
        Dim propertyChangingField As FieldInfo = myType.GetField("PropertyChangingEvent", BindingFlags.NonPublic Or BindingFlags.Instance)
        Dim propertyChangingDelegate As PropertyChangingEventHandler = propertyChangingField.GetValue(Me)
        Dim delegateType As Type = Nothing

        For Each thisDelegate In propertyChangingDelegate.GetInvocationList()
            delegateType = thisDelegate.Target.GetType()
            If delegateType.FullName.Equals(StandardChangeTrackerName) Then
                propertyChangingDelegate = thisDelegate
                hasContext = True
                Exit For
            End If
        Next

        If hasContext Then
            Dim targetField = propertyChangingDelegate.Target
            Dim servicesField As FieldInfo = targetField.GetType().GetField("services", BindingFlags.NonPublic Or BindingFlags.Instance)
            If servicesField IsNot Nothing Then

                Dim servicesObject = servicesField.GetValue(targetField)

                Dim contextField As FieldInfo = servicesObject.GetType.GetField("context", BindingFlags.NonPublic Or BindingFlags.Instance)

                _context = contextField.GetValue(servicesObject)

            End If
        End If
    
        Return _context
    End Get
    Set(ByVal value As DataClasses1DataContext)

        _context = value

    End Set

End Property

ChangeTracking がオンになっているコンテキストに現在アタッチされている場合、オブジェクトはその DataContext のみを見つけることができることに注意してください。このプロパティは、DataContext がオブジェクトの OnPropertyChanging イベントをサブスクライブして、オブジェクトの存続期間中の変更を監視しているという事実に依存しています。

これが役に立った場合は、この投稿に賛成票を投じてください。

リフレクションを使用してイベント ハンドラーを検索する方法の詳細については、次を参照してください。

于 2009-06-12T11:11:00.433 に答える
0

DataContext をコードに (手動で) 渡すだけでよいと思います。ごめん。

于 2008-11-25T12:52:39.930 に答える