2009-08-24 3 views
2

Ich habe ein Linq-To-SQL-Objekt obj vom Typ MyClass, die ich über meinen Datenkontext geladen habe.Was ist der sauberste Weg, um ein Linq-Objekt "schmutzig" zu machen?

Jetzt möchte ich das Objekt zum Speichern zwingen, auch wenn sich keine Felder tatsächlich geändert haben, so dass die Speicheraktion einige Auslöser hinter den Kulissen auslösen kann.

Was ist der einfachste Weg, um meinen Datenkontext zu denken, dass obj verschmutzt ist, so dass ein Anruf an SubmitChanges() wird obj gespeichert werden?

+0

Wie wäre es mit Berufung Attach (obj, wahr) auf dem Tisch von der dc? – meandmycode

+0

@meandmycode .Attach (obj, true) würde unter bestimmten Umständen funktionieren, aber nicht wenn: a) das Objekt bereits an den Datenkontext angehängt ist oder b) das Objekt ist detached aber hat keine Versionsmember (timestamp/rowversion) – KristoferA

Antwort

7

Nur eine Eigenschaft auf einen Dummy-Wert ändern und dann zurück ...

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

Edit: lassen Sie mich das zurück zu nehmen. Der L2S Change Tracker wird dadurch nicht getäuscht. Der einfachste/sauberste/sicherste Weg, wenn Sie keine der vorhandenen Spalten ändern möchten, ist wahrscheinlich, eine neue Spalte hinzuzufügen und diese zu ändern.

Wenn Sie absolut keine db-Änderungen vornehmen können (d. H. Eine neue Spalte hinzufügen), dann ist es möglicherweise eine Option, den Change-Tracker mit Reflektion aufzurufen. Ich habe es nicht versucht, aber es sieht so aus, als wäre der Weg dahin (ungefähr):

1) der datacontext hat ein privates Mitglied namens services.
2) Dienste zeigt auf eine CommonDataServices, die eine private Member-Tracker und ein internes Mitglied ChangeTracker (die ehemalige zurückgibt).
3) Tracker ändern verfügt über eine interne Methode GetTrackedObject, die ein verfolgtes Objekt zurückgibt.
4) TrackedObject eine ConvertToModified Methode hat ...

Edit # 2: Getestet habe ich nur die Reflexion Weg über und es scheint zu funktionieren. Z.B .:

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

... und die Umsetzung von MakeDirty ist:

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

Ah, ich habe mich über diese Idee gewundert. Erkennt Linq die Verschmutzung durch die Tatsache, dass die "Set" -Methode einer Eigenschaft aufgerufen wurde, oder durch Vergleichen der geladenen Werte mit den aktuellen Werten? Von dem, was du sagst, ist es das erstere. –

+0

Ich war zu schnell beim Antworten - ich lag falsch ... :) – KristoferA

+0

Aha. Ich habe das auch entdeckt. Schade, das wäre für mich am einfachsten gewesen. Ich mag nicht all diese dunklen Künste, private Mitglieder des Datenkontextes anzugreifen ... scheint irgendwie gefährlich zu sein. Also denke ich, dass es das "schmutzige" Feld für mich sein wird. Vielen Dank! –

0

Sie könnten versuchen, 2 vorträgt, wenn das nicht geht, etwas anderes zu brechen? Daher können Sie einfach eine Variation der ersten Antwort von Kristofer verwenden:

Irgendwelche Vorteile für Ihre Zwecke?

+0

Funktioniert, aber führt zu unnötigen Db-Roundtrips ... – KristoferA

+0

Einverstanden, aber es funktioniert, wenn er keine zusätzlichen Spalten zu db hinzufügen kann – h4xxr

Verwandte Themen