.net - 确定 Linq to Sql 查询的源 DataContext

标签 .net linq linq-to-sql datacontext

在我的应用程序中,我有几个 DataContexts 连接到具有不同模式的不同数据库。在自定义用户控件中,我显示查询结果并让用户编辑它们,当用户编辑数据时,我希望将更改保留到数据库中。为此,我需要对源 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;
}

最佳答案

是的 - 使用反射是确定查询所属的 DataContext 的唯一方法。这与触发查询时创建的数据对象相同。
下面的内容并没有严格回答 Rune 的问题,但如果您想使用反射来确定数据对象是否附加到数据上下文并由数据上下文监视,则可能会有所帮助:
以下代码定义了一个 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
  • https://web.archive.org/web/20131213074318/http://bobpowell.net/eventsubscribers.aspx
  • 关于.net - 确定 Linq to Sql 查询的源 DataContext,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/317114/

    相关文章:

    c# - 如何处理从 DataContext.ExecuteQuery 返回的未知类型的对象

    c# - 克隆 Linq 对象错误 "Object graph for type ' TestLinq.PersonAddress' 包含循环,如果禁用引用跟踪则无法序列化。”

    c# - 使用 EF 的单例设计模式和异步方法

    .net - 在 F# 中使用 Lambda 表达式创建委托(delegate)

    c# - 如何让光标变成等待光标?

    c# - 如何在 Collection<T> 上使用 ToList

    c# - 向 Entity Framework 添加自定义属性?

    C# linq 从列表的子列表构建表

    linq-to-sql - 如何强制 linq to sql 在生成的 sql 中将 ntext 列转换为 nvarchar(max) ?

    c# - 动态 LINQ - 有 .NET 4 版本吗?