2009-03-27 9 views
10

Einige Hintergrund: Ich habe eine Datenbank, die ich verwenden möchte, linq-to-sql durch eine C# -Anwendung zu aktualisieren. Eine der Spalten in dieser Tabelle hat einen XML-Datentyp.Linq-to-SQL mit XML-Datenbankfeldern - Warum funktioniert das?

Jede andere Spalte in dieser Tabelle (die nicht von einem XML-Datentyp ist) wird einwandfrei aktualisiert, aber wenn ich Änderungen am XML-Feld vornahm, wird das Programm (scheinbar) korrekt ausgeführt, aber das Feld behält immer seine Originalwert, nachdem ich SubmitChanges() ausgeführt habe.

sah ich mich um das Internet und fand ähnliche Probleme ein paar Beiträge über Microsoft Connect Diagnose und stolperte schließlich auf die Lösung here:

Um diese XML-Feld Update zwingen wird, nicht tun:

XElement tmp = MyLinqObject.XmlField; 
MyLinqObject.XmlField = null; 
MyLinqObject.XmlField = tmp; 

anstatt dass LINQ zu zwingen XML-Spalte zu aktualisieren, ein geklonte Objekt zuordnen:

MyLinqObject.XmlField = new XElement (MyLinqObject.XmlField); 

ich kann bestätigen, dass dies tatsächlich zu wor scheint k, aber ich weiß nicht genau warum. Meine einzige Vermutung ist, dass die XmlField-Eigenschaft einen eindeutigen Bezeichner auf dem Heap hat und dass Sie ihm durch das Erstellen eines Klons einen neuen eindeutigen Bezeichner zugewiesen haben. Wenn Linq dann die Abfrage generiert, versucht es nicht einmal zu sehen, ob das Feld aktualisiert wurde, da es eine neue ID hat, schreibt es einfach den Wert in die Datenbank. Aber ich spekuliere einfach und hoffe, dass jemand anderes ein besseres Verständnis für die Vorgänge hinter den Kulissen vermitteln kann.

EDIT: Jons Post-Adresse, der Grund für das Problem (wie es auf der MS Connect-Website erklärt wird) besteht darin, dass „das XML-Feld nicht aktualisiert, da Linq-to-SQL behandelt nicht die XElement .Changed Ereignis ".

Für meine Implementierung der Code, suchen so etwas wie das funktioniert endet:

MyXElementProperty.SetElementValue("Author", author); 

MyXElementProperty = new XElement(MyXElementProperty); 

Als Referenz (auf alle anderen, dass diese Frage findet), folgende Arbeiten auch:

MyXElementProperty = new XElement(MyXElementProperty); 

MyXElementProperty.SetElementValue("Author", author); 

Antwort

10

Wenn Sie es zu einem neuen XElement machen, machen Sie ein anderes Objekt. Es ist möglich, dass zum Erkennen von "Verjährung" die Referenzgleichheit verwendet wird, die dies offensichtlich als neuen Wert behandelt.

An welchem ​​Punkt nehmen Sie Änderungen am Element vor? Ich würde erwarten, dass LINQ zu SQL eine Kopie des ursprünglichen Werts im Cache gespeichert und dann mit dem neuen Wert vergleichen. Wenn es diese "zwischengespeicherte Kopie" nur durch Kopieren der Referenz nimmt, dann wird es, egal was Sie mit dem Objekt machen, immer denken, dass die beiden gleich sind. Wenn Sie stattdessen ein neues Element erstellen und dann ändern, das, dann wird das alte Objekt immer noch den alten Wert haben, so dass der Vergleich versteht, dass Sie Änderungen vorgenommen haben. Ist das sinnvoll?

+0

Aktualisiert, um hoffentlich Ihre Fragen zu beantworten. Insgesamt macht Ihre Erklärung jedoch Sinn. – jerhinesmith

+1

Sie setzen also die Eigenschaft * nachdem * Sie die Änderung vorgenommen haben? Ich bin etwas überrascht, dass das funktioniert, um ehrlich zu sein ... Ich würde erwarten, dass es das gleiche Problem hat.Vielleicht ist es wirklich nur Referenzgleichheit. –

+0

Eigentlich habe ich es gerade versucht, nachdem ich die Reihenfolge geändert habe und beide Möglichkeiten scheinen zu funktionieren. Nicht sicher, ob das mehr oder weniger verwirrend ist. – jerhinesmith

0

Dies war eine sehr "andere" Problemumgehung. Ich verbrachte eine Weile damit, herauszufinden, warum das XML-Feld in der Datenbank nicht hochgeladen wurde. Das neue XElement (updatedXElement) hat auch für mich funktioniert!