Dot-Net
獲取對象的 DataContext
如果我有 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; } } }以及應用程序中的其他地方:
public static void DoSomethingWithCustomer( Customer customer ) { // some operations // now, I want save changes to the database }如何獲取跟踪“客戶”對象更改的 DataContext 實例?
編輯:為什麼我不想將 DataContext 傳遞給方法。
- 始終傳遞 2 個對象而不是 1 個是整個應用程序的“醜陋”模式。
- 每個業務對象的方法都需要下一個參數。
- 收藏將需要從“列表”更改為“列表>”。
這兩點將更難維護 - 開發人員必須每次都設置正確的 DataContext 實例(容易創建錯誤),儘管 DataContext 知道具體對像是否附加到另一個 DataContext。
2)我想要(目前版本的應用程序使用它)處理來自不同“地方”的對象集合的“任何”業務邏輯(例如,通過拖放操作浮動視窗)。
Currentyl 我們使用自定義類型的數據集,因此有關更改的資訊位於數據行(DataRow = 業務對象)中,獲取它沒有問題,或者創建一個複製然後將其保存到數據庫中。
Kevin - 我感到你的痛苦……當你圍繞你的業務對象建構業務邏輯時,有時你只需要訪問對象所屬的 DataContext,因為不知道 DataContext 不得不放置你的程式碼在降低程式碼可維護性的地方。
我編寫了以下程式碼(恐怕是 VB),它提供了一個 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這是一個 C# 版本:
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); }請注意,如果對象目前附加到已打開 ChangeTracking 的上下文,則該對像只能找到它的 DataContext。此屬性依賴於 DataContext 已訂閱對象的 OnPropertyChanging 事件以監視對像生命週期內的更改這一事實。
如果這有幫助,請給這篇文章投票。
有關使用反射查找事件處理程序的更多資訊: