2008-12-15 22 views
10

是否有任何簡單的方法來訪問linq2sql實體類中的DataContext訪問實體類中的LINQ-2-SQL DataContext

我試圖創建類似EntitySet的東西,但我無法弄清楚EntitySet如何訪問創建實體對象的上下文。

我想要一個常規的linq2sql實體類,以便類訪問創建它的DataContext。我知道這是可能的,因爲當你有一個主鍵的實體類linq2sql給你的選項加載所有的孩子,而不會創建一個新的DataContext

回答

3

基本上沒有。

EntitySet<T>類具有由數據上下文分配的內部Source屬性,它是按照數據按需獲取的屬性。但是,數據類本身沒有任何相似之處。

但是,我相信實體框架有更多的訪問權限,這是以強制對象層次結構爲代價的。與實體框架不同,LINQ-to-SQL(按設計)可以與常規的持久性無關類一起使用 - 所以它並不假定它可以訪問這種類型的數據。

1

實體類不應該知道它的只是表,但數據上下文的映射數據上下文的具有所有實體的知識和連接屬性

您可以鏈接到子表通過父實體類,因爲實體關係而不是通過數據上下文

數據上下文類將用在實體消耗的最後,我沒有看到實體需要知道的情況下,

如果你可以告訴具體情況,我們可以嘗試其他方法。

+1

我有同樣的問題,雖然我理解你的論點(相信我,我贊成它),但我對此有真實的需求。 在我們的一些實體部分類中,我們添加了一些必須根據實體的屬性來查詢數據庫的屬性,以獲取一些其他實體集合,這些實體並不直接與SQL Server關聯。這真的很難看,因爲我們在調用這些屬性時創建一個新的數據上下文(其中一些屬於循環)。 – 2010-04-18 04:02:31

0

我確切地知道你的意思。我們應該在實體的部分類中進行計算/驗證,但是如果實體無法訪問datacontext,那麼我們可以做多少?例如,在我的SalesOrder對象中,只要「寄送地址」地址發生變化,SalesOrder就需要查詢數據庫以確定是否適用於該州/郵政編碼。我一直在爭取這一段時間,但今天我失敗了,並採用了醜陋的方法,但目前爲止這麼好。基本上,我所做的只是在分部類中創建一個「Context」屬性,並在創建實體時將其設置爲datacontext。

Partial Class SalesOrder 
    Private moContext As L2S_SalesOrdersDataContext 

    Friend Property Context() As L2S_SalesOrdersDataContext 
     Get 
      Return moContext 
     End Get 
     Set(ByVal value As L2S_SalesOrdersDataContext) 
      moContext = value 
     End Set 
    End Property 
... 

YMMV,特別是如果你是分離你的實體。

0

基本上,你可以用一點黑客來做到這一點。 DataContext的附加一個StandardChangeTracker到你的實體:

 
      DataContext context = null; 
      object changeTracker = (from i in o1.GetInvocationList() where i.Target.GetType().FullName == "System.Data.Linq.ChangeTracker+StandardChangeTracker" select i.Target).FirstOrDefault(); 
      if (changeTracker != null) // DataCOntext tracks our changes through StandardChangeTracker 
      { 
       object services = Reflector.GetFieldValue(changeTracker, "services"); 
       context = (DataContext)Reflector.GetFieldValue(services, "context"); 
      } 

凡Reflector.GetFieldValue等於

 
     public static object GetFieldValue(object instance, string propertyName) 
     { 
      return instance.GetType().GetField(propertyName, BindingFlags.Instance | BindingFlags.NonPublic).GetValue(instance); 
     } 
6

我剛剛做同樣的事情。這是我的解決方案(儘管可能不是最好的方法,但至少相當優雅):

首先,爲所有實體創建一個接口,以實現從INotifyPropertyChanging繼承。這是用來連接一些擴展方法,並保持我們的實現很好獨立。在我的情況下,接口被稱爲ISandboxObject:

public interface ISandboxObject : INotifyPropertyChanging 
{ 
    // This is just a marker interface for Extension Methods 
} 

然後創建一個新的靜態類包含一個擴展方法獲得的DataContext。這是通過在連接到INotifyPropertyChanging.PropertyChanging事件的LINQ變更跟蹤器上查找事件處理程序來實現的。一旦我們發現變更跟蹤,我們可以從那裏獲得的DataContext:

/// <summary> 
    /// Obtain the DataContext providing this entity 
    /// </summary> 
    /// <param name="obj"></param> 
    /// <returns></returns> 
    public static DataContext GetContext(this ISandboxObject obj) 
    { 
     FieldInfo fEvent = obj.GetType().GetField("PropertyChanging", BindingFlags.NonPublic | BindingFlags.Instance); 
     MulticastDelegate dEvent = (MulticastDelegate)fEvent.GetValue(obj); 
     Delegate[] onChangingHandlers = dEvent.GetInvocationList(); 

     // Obtain the ChangeTracker 
     foreach (Delegate handler in onChangingHandlers) 
     { 
      if (handler.Target.GetType().Name == "StandardChangeTracker") 
      { 
       // Obtain the 'services' private field of the 'tracker' 
       object tracker = handler.Target; 
       object services = tracker.GetType().GetField("services", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(tracker); 

       // Get the Context 
       DataContext context = services.GetType().GetProperty("Context").GetValue(services, null) as DataContext; 
       return context; 
      } 
     } 

     // Not found 
     throw new Exception("Error reflecting object"); 
    } 

現在你有一個很好的擴展方法,它會爲您提供從實施ISandboxObject任何對象一個DataContext。在憤怒中使用它之前,請確保在其中添加更多錯誤檢查!