2009-03-27 7 views
10

En arrière-plan: J'ai une base de données que je veux utiliser linq-to-sql pour mettre à jour via une application C#. Une des colonnes de cette table a un type de données XML.Linq-to-SQL avec les champs de base de données XML - Pourquoi cela fonctionne-t-il?

Chaque autre colonne de ce tableau (qui n'est pas un type de données XML) est parfaitement mise à jour, mais lorsque je suis allé modifier le champ XML, le programme s'exécute (apparemment) correctement, mais le champ conserve toujours son valeur d'origine après je cours SubmitChanges().

Je regardais autour de l'Internet et a trouvé quelques messages sur Microsoft Connect diagnostiquer des problèmes similaires et finalement trébuché sur la solution here:

Pour forcer la mise à jour de champ XML cela ne va pas:

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

au lieu de cela pour forcer LINQ mettre à jour la colonne XML assigner un objet cloné:

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

Je peux confirmer que cela ne semble en effet wor k, mais je ne sais pas exactement pourquoi. Ma seule supposition est que la propriété XmlField a une sorte d'identifiant unique sur le tas et qu'en faisant un clone, vous lui avez assigné un nouvel identifiant unique. Lorsque Linq génère alors la requête, il n'essaie même pas de voir si le champ a été mis à jour, puisqu'il a un nouvel identifiant, il écrit simplement la valeur dans la base de données. Mais je ne fais que spéculer et j'espère que quelqu'un d'autre pourra mieux comprendre ce qui se passe dans les coulisses.

EDIT: Pour répondre à la poste de Jon, la raison de la question (comme il est expliqué sur le MS Connect le site) est que « le champ XML ne met pas à jour parce que LINQ to SQL ne gère pas le XElement Evénement .Changed ".

Pour ma mise en œuvre, le code qui fonctionne finit à la recherche quelque chose comme ceci:

MyXElementProperty.SetElementValue("Author", author); 

MyXElementProperty = new XElement(MyXElementProperty); 

Pour référence (à quelqu'un d'autre qui trouve cette question), ce qui suit fonctionne aussi:

MyXElementProperty = new XElement(MyXElementProperty); 

MyXElementProperty.SetElementValue("Author", author); 

Répondre

10

Lorsque vous créez un nouveau XElement, vous créez un objet différent. Il est possible que pour détecter la "staleness", il utilise l'égalité de référence, ce qui traiterait évidemment cela comme une nouvelle valeur.

À quel moment modifiez-vous réellement l'élément? Je voudrais attendre LINQ à SQL pour avoir une copie en cache de la valeur d'origine, puis comparez cela avec la nouvelle valeur. Si vous prenez cette "copie cachée" en copiant simplement la référence, alors quoi que vous fassiez pour cet objet, il pensera toujours que les deux sont égaux. Si à la place vous créez un nouvel élément, puis modifiez que, l'ancien objet conservera l'ancienne valeur, de sorte que la comparaison comprendra que vous avez apporté des modifications. Cela a-t-il du sens?

+0

Mis à jour pour répondre, je l'espère, à vos questions. Dans l'ensemble, votre explication a du sens, cependant. – jerhinesmith

+1

Vous définissez donc la propriété * après * vous avez effectué le changement? Je suis un peu surpris que ça marche, pour être honnête ... je m'attendrais à avoir le même problème.Peut-être que c'est simplement en utilisant l'égalité de référence. –

+0

En fait, je l'ai juste essayé après avoir changé l'ordre et les deux manières semblent fonctionner. Je ne sais pas si cela le rend plus ou moins confus. – jerhinesmith

0

C'était une solution de contournement très "différente", j'ai passé un moment à essayer de comprendre pourquoi le champ XML sur la base de données, n'a pas été téléchargé. Le nouveau XElement (updatedXElement) a fonctionné pour moi aussi!

Questions connexes