2009-08-24 2 views
2

У меня есть объект Linq-To-SQL obj типа MyClass, который я загрузил через мой контекст данных.Какой самый чистый способ сделать объект Linq «грязным»?

Теперь я хочу, чтобы этот объект сохранялся, даже если поля не изменились, так что действие сохранения может выставить некоторые триггеры за кулисами.

Какой самый простой способ сделать мой контекст данных считающим, что obj грязный, так что вызов SubmitChanges() приведет к сохранению obj?

+0

Как насчет вызова Attach (obj, true) в таблице от постоянного тока? – meandmycode

+0

@meandmycode .Attach (obj, true) будет работать при некоторых обстоятельствах, но не если: a) объект уже прикреплен к datacontext или b) объект отсоединен, но не имеет члена версии (временная метка/rowversion) – KristoferA

ответ

7

Просто измените свойство фиктивной стоимости, а затем обратно ...

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

Edit: позвольте мне считать, что обратно. Отслеживание изменений L2S не будет обмануто этим. Самый простой/чистый/безопасный способ, если вы не хотите менять какой-либо из существующих столбцов, вероятно, должен добавить новый столбец и изменить его.

Если вы абсолютно не можете внести какие-либо изменения в db (т. Е. Добавить новый столбец), то переход к трекеру изменений с отражением может быть вариантом. Я не пробовал, но похоже, что маршрут к нему будет (примерно):

1) у datacontext есть частный член, называемый сервисами.
2) Службы указывают на CommonDataServices, у которого есть отдельный участник-трекер и внутренний член ChangeTracker (возврат первого).
3) Сменные трекеры имеют внутренний метод GetTrackedObject, который возвращает TrackedObject.
4) TrackedObject имеет метод ConvertToModified ...

Edit # 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» любого свойства, или путем сравнения загруженных значений с текущими значениями? Из того, что вы говорите, это первый. –

+0

Я слишком быстро ответил - я ошибся ... :) – KristoferA

+0

Aha. Я также обнаружил это. Жаль, это было бы самым легким для меня. Мне не очень нравятся все эти темные искусства атакующих частных членов контекста данных ... кажется, что это опасно. Поэтому я думаю, что это будет для меня «грязное» поле. Благодаря! –

0

Вы можете попробовать 2 ПРЕДСТАВЛЯЕТ, если это не будет ломать что-нибудь еще? Поэтому вы можете просто использовать вариант первого ответа Кристофера:

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 roundtrips ... – KristoferA

+0

Согласовано, но работает, если он не может добавить дополнительные столбцы в db – h4xxr

Смежные вопросы