Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net 获取对象';数据上下文_.net_Linq To Sql_C# 3.0_Datacontext - Fatal编程技术网

.net 获取对象';数据上下文

.net 获取对象';数据上下文,.net,linq-to-sql,c#-3.0,datacontext,.net,Linq To Sql,C# 3.0,Datacontext,如果我有LINQ对象: public class SampleDataContext : DataContext { public Table<Customer> Customers { get { return this.GetTable<Customer>(); } } public SampleDataContext( string connectionString ) : base( connectionString ) { } } [Table

如果我有LINQ对象:

public class SampleDataContext : DataContext {
    public Table<Customer> Customers { get { return this.GetTable<Customer>(); } }
    public SampleDataContext( string connectionString ) : base( connectionString ) { }
}

[Table( Name="dbo.tblCustomers" )]
public class Customer {
    private Guid? customerID;
    [Column( Storage="customerID", DbType="uniqueidentifier NOT NULL", IsPrimaryKey=true )]
    public Guid? CustomerID {
        get { return this.customerID; }
        set { this.customerID = value; }
    }

    private string customerName;
    [Column( Storage = "customerName", DbType = "nvarchar(255) NOT NULL" )]
    public string CustomerName {
        get { return this.customerName; }
        set { this.customerName = value; }
    }
}
如何获取跟踪“customer”对象更改的DataContext实例

编辑:为什么我不想将DataContext传递到方法中。

1) 始终传递2个对象而不是1个对象对于整个应用程序来说是“丑陋”的模式

  • 方法将需要每个业务对象的下一个参数
  • 集合将需要从“列表”更改为“列表>”
这两点都很难维护——开发人员每次都必须设置正确的DataContext实例(很容易创建错误),尽管DataContext知道具体对象是否连接到另一个DataContext

2) 我希望(当前版本的应用程序使用它)处理来自不同“位置”的对象集合上的“任何”业务逻辑(例如,通过拖放操作的浮动窗口)


Currentyl我们使用自定义类型的数据集,因此有关更改的信息位于数据行(DataRow=业务对象)中,获取它或创建克隆然后将其保存到数据库中并不成问题。

最简单的方法是将DataContext传递到方法中


但是,你也可以考虑改变你的设计,让你遵循“一个方法只有一个目的”的规则,在这种情况下,你不想用“修改”的方法来“保存”。

< P>部分乐趣在于你不能确定对象知道谁在跟踪他。如果对象具有数据感知/延迟加载属性,那么您可能能够通过反射跟踪上下文,但实际上这将是一个混乱。简单地将数据上下文传递给需要它的代码会更干净。

Kevin-我感觉到了你的痛苦。。。当您围绕业务对象构建业务逻辑时,有时您只需要访问对象所属的DataContext,因为不知道DataContext菜单就必须将代码放在降低代码可维护性的地方

我编写了以下代码(恐怕是VB),它提供了一个可以放置在数据对象上的上下文属性,然后用于返回对象所附加的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
这是一个C版本:

请注意,如果对象当前连接到打开了ChangeTracking的上下文,则该对象只能定位其DataContext。此属性依赖于DataContext已订阅对象的OnPropertyChange事件以监视对象生命周期内的更改这一事实

如果这有帮助,请在这篇文章上投票

有关使用反射查找事件处理程序的详细信息:


我想在“整个”应用程序中使用我的对象。为每个业务对象实例传递DataContext是不实际的:/。如果您对我有意见,您就不应该使用这种方法:这意味着数据上下文也是长期存在的(因为两者是隐式链接的),但是数据上下文通常应该被认为是短期资源。我修改了我们的需求和linq能力,看来linq到sql不是正确的方式,我们应该走。也许linq to实体可以提供所需的功能。谢谢你们的回答。+1这条路有点“黑”,但很可能是我搜索到的。现在,我正在使用LINQ IQuerableToolkit(来自CodePlex),我非常高兴:)。我添加了一个C版本的方法,并做了一些小改动:1)它是一个方法而不是属性,2)如果对框架内部的更改破坏了该方法,它会故意失败而不是返回null。
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
public DataContext GetMyDataContext()
{
    // Find the StandardChangeTracker listening to property changes on this object.
    // If no StandardChangeTracker is listening, then this object is probably not
    // attached to a data context.
    var eventField = this.GetType().GetField("PropertyChangingEvent", BindingFlags.NonPublic | BindingFlags.Instance);
    var eventDelegate = eventField.GetValue(this) as Delegate;
    if (eventDelegate == null)
        return null;
    eventDelegate = eventDelegate.GetInvocationList().FirstOrDefault(
        del => del.Target.GetType().FullName == "System.Data.Linq.ChangeTracker+StandardChangeTracker");
    if (eventDelegate == null)
        return null;

    // Dig through the objects to get the underlying DataContext.
    // If the following fails, then there was most likely an internal change
    // to the LINQ-to-SQL framework classes.
    var targetField = eventDelegate.Target;
    var servicesField = targetField.GetType().GetField("services", BindingFlags.NonPublic | BindingFlags.Instance);
    var servicesObject = servicesField.GetValue(targetField);
    var contextField = servicesObject.GetType().GetField("context", BindingFlags.NonPublic | BindingFlags.Instance);
    return (DataContext)contextField.GetValue(servicesObject);
}