2009-08-24 46 views
2

我有我通過數據上下文加載的類型爲MyClass的Linq-To-SQL對象obj使Linq對象變得「髒」的最簡潔的方法是什麼?

現在我想強制保存這個對象,即使沒有實際的字段已經改變,這樣保存動作可以在幕後設置一些觸發器。

什麼是使我的數據上下文認爲obj很髒的最簡單的方法,以致於調用SubmitChanges()將導致obj被保存?

+0

那麼從dc上的表調用Attach(obj,true)怎麼樣? – meandmycode 2009-08-24 10:44:50

+0

@meandmycode .Attach(obj,true)可以在某些情況下工作,但在以下情況下不起作用: a)對象已經附加到datacontext 或 b)對象已分離,但沒有版本成員(時間戳/排列) – KristoferA 2009-08-28 08:10:30

回答

7

屬性只是更改爲虛值,然後回來...

var value = obj.SomeField; 
obj.SomeField = "dummy"; 
obj.SomeField = value; 
dc.SubmitChanges(); 

編輯:讓我收回這句話。 L2S變化跟蹤器不會被這個愚弄。如果您不想更改任何現有列,最簡單/最乾淨/最安全的方式可能是添加一個新列並更改該列。

如果絕對不能進行任何數據庫更改(即添加一個新列),那麼使用反射進行更改跟蹤器可能是一個選項。我沒有嘗試過,但它看起來像是(大致)的路線:

1)datacontext有一個叫做services的私有成員。
2)服務指向一個CommonDataServices,它有一個私人成員跟蹤器和一個內部成員ChangeTracker(返回前者)。
3)變更跟蹤器有一個GetTrackedObject內部方法,返回一個TrackedObject。
4)TrackedObject有ConvertToModified方法...

編輯#2:我只是測試更高的反射路線,它似乎工作。例如: -

  using (advWorksDataContext dc = new advWorksDataContext()) 
     { 
      Employees emp = dc.Employees.FirstOrDefault(); 
      dc.MakeDirty(emp); 
      dc.SubmitChanges(); 
     } 

...和MakeDirty的實現是:

public static class DCExtensions 
{ 
    internal static void MakeDirty(this System.Data.Linq.DataContext dc, object someEntity) 
    { 
     //get dc type 
     Type dcType = dc.GetType(); 
     while (dcType != typeof(System.Data.Linq.DataContext)) 
     { 
      dcType = dcType.BaseType; 
     } 

     //get hold of the CommonDataServices thing in the DC 
     System.Reflection.FieldInfo commonDataServicesField 
      = dcType.GetField("services", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic); 
     object commonDataServices = commonDataServicesField.GetValue(dc); 
     Type commonDataServicesType = commonDataServices.GetType(); 

     //get hold of the change tracker 
     System.Reflection.PropertyInfo changeTrackerProperty 
      = commonDataServicesType.GetProperty("ChangeTracker", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic); 
     object changeTracker = changeTrackerProperty.GetValue(commonDataServices, null); 
     Type changeTrackerType = changeTracker.GetType(); 

     //get the tracked object method 
     System.Reflection.MethodInfo getTrackedObjectMethod 
      = changeTrackerType.GetMethod("GetTrackedObject", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic); 
     object trackedObject = getTrackedObjectMethod.Invoke(changeTracker, new object[] { someEntity }); 

     //get the ConvertToModified method 
     Type trackedObjectType = trackedObject.GetType(); 
     System.Reflection.MethodInfo convertToModifiedMethod 
      = trackedObjectType.GetMethod("ConvertToModified", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic); 

     //call the convert to modified method 
     convertToModifiedMethod.Invoke(trackedObject, null); 
    } 
} 
+0

啊,我想知道這個想法。 Linq是否通過調用任何屬性的「Set」方法或通過比較加載值與當前值來確定骯髒程度?從你所說的,這是前者。 – 2009-08-24 09:14:14

+0

我回復得太快 - 我錯了...... :) – KristoferA 2009-08-24 09:54:32

+0

啊哈。我也發現了這一點。可惜,那對我來說會是最簡單的。我不太喜歡所有這些攻擊數據背景的私人成員的黑暗藝術......似乎有點危險。所以我想畢竟這對我來說將是「骯髒」的領域。謝謝! – 2009-08-24 10:23:54

0

你可以嘗試2次的提交如果這不是要打破什麼嗎?因此你可以使用的Kristofer的第一個答案的變化:

Just change a property to a dummy value, save it, and then change back... 
var value = obj.SomeField; 
obj.SomeField = "dummy"; 
dc.SubmitChanges(); 
obj.SomeField = value; 
dc.SubmitChanges(); 

任何好你的目的是什麼?

+0

工作,但會導致不必要的db往返... – KristoferA 2009-08-24 10:44:00

+0

同意,但如果他無法將任何其他列添加到db,則可行 – h4xxr 2009-08-24 11:04:19

相關問題