使Linq对象变得“脏”的最简洁方法是什么?

时间:2009-08-24 09:07:01

标签: c# linq linq-to-sql

我有一个类型obj的Linq-To-SQL对象MyClass,我已经通过我的数据上下文加载了它。

现在我想强制该对象保存,即使没有实际更改过的字段,这样保存操作可以在幕后设置一些触发器。

让我的数据上下文认为obj很脏的最简单方法是什么,以便调用SubmitChanges()会导致obj被保存?

2 个答案:

答案 0 :(得分: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:我刚测试了上面的反射路线,似乎有效。 E.g:

            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);
    }
}

答案 1 :(得分: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();

对你的目的有什么好处吗?