确定Linq to Sql查询的源DataContext

时间:2008-11-25 11:52:33

标签: .net linq linq-to-sql datacontext

在我的应用程序中,我有几个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;
}

2 个答案:

答案 0 :(得分: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事件以监视对象生命周期内的更改。

如果这样做有帮助,请向我们投票。

有关使用反射查找事件处理程序的更多信息: http://weblogs.asp.net/avnerk/archive/2007/03/29/reflecting-over-an-event.aspx http://www.bobpowell.net/eventsubscribers.htm

答案 1 :(得分:0)

我认为你必须简单地将DataContext传递给代码(手动)。遗憾。