我有我通過數據上下文加載的類型爲MyClass
的Linq-To-SQL對象obj
。使Linq對象變得「髒」的最簡潔的方法是什麼?
現在我想強制保存這個對象,即使沒有實際的字段已經改變,這樣保存動作可以在幕後設置一些觸發器。
什麼是使我的數據上下文認爲obj
很髒的最簡單的方法,以致於調用SubmitChanges()
將導致obj
被保存?
我有我通過數據上下文加載的類型爲MyClass
的Linq-To-SQL對象obj
。使Linq對象變得「髒」的最簡潔的方法是什麼?
現在我想強制保存這個對象,即使沒有實際的字段已經改變,這樣保存動作可以在幕後設置一些觸發器。
什麼是使我的數據上下文認爲obj
很髒的最簡單的方法,以致於調用SubmitChanges()
將導致obj
被保存?
屬性只是更改爲虛值,然後回來...
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);
}
}
啊,我想知道這個想法。 Linq是否通過調用任何屬性的「Set」方法或通過比較加載值與當前值來確定骯髒程度?從你所說的,這是前者。 – 2009-08-24 09:14:14
我回復得太快 - 我錯了...... :) – KristoferA 2009-08-24 09:54:32
啊哈。我也發現了這一點。可惜,那對我來說會是最簡單的。我不太喜歡所有這些攻擊數據背景的私人成員的黑暗藝術......似乎有點危險。所以我想畢竟這對我來說將是「骯髒」的領域。謝謝! – 2009-08-24 10:23:54
你可以嘗試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();
任何好你的目的是什麼?
工作,但會導致不必要的db往返... – KristoferA 2009-08-24 10:44:00
同意,但如果他無法將任何其他列添加到db,則可行 – h4xxr 2009-08-24 11:04:19
那麼從dc上的表調用Attach(obj,true)怎麼樣? –
meandmycode
2009-08-24 10:44:50
@meandmycode .Attach(obj,true)可以在某些情況下工作,但在以下情況下不起作用: a)對象已經附加到datacontext 或 b)對象已分離,但沒有版本成員(時間戳/排列) – KristoferA 2009-08-28 08:10:30