4

One of my entities in my LinqToSql model has a field of type XElement, mapped to an XML column in SQL Server.

When I do the following:

myEntity.MyXmlField.Add(new XAttribute("attribute", "value"));
...
DataContext.SubmitChanges();

The field does not get updated in the database (but other fields do). I take it that the DataContext cannot track changes made inside the XElement and thus this field is not marked as dirty and does not get updated.

Is this the correct assumption and how can I fix it?

EDIT

After reading the link that The Scrum Meister provided, it looks like

myEntity.MyXmlField = new XElement(myEntity.MyXmlField);

will solve the issue.

However this solution is quite specific to XElement (as it's easy to clone it), and involves a lot of processing if the XElement is large.

There's got to be a general way of letting the DataContext know that a field has changed.

Xavier Poinas
  • 19,377
  • 14
  • 63
  • 95

3 Answers3

3

Alright, it looks like this is a known issue: http://connect.microsoft.com/VisualStudio/feedback/details/360433/linq-to-sql-xml-fields-dont-update

Microsoft's recommendation is to use

myEntity.MyXmlField = new XElement(myEntity.MyXmlField);

So I take it there is no better or general way of fixing this.

Simon_Weaver
  • 140,023
  • 84
  • 646
  • 689
Xavier Poinas
  • 19,377
  • 14
  • 63
  • 95
  • Nope, I spent quite a bit of head-against-the-wall time with this a couple of years ago. It 'makes sense' in a way, when you consider that all other types that are pushed to SQL are typically value types, and this (a reference type) is a bit of an exception. You can create the new reference before updating (as in my answer) or after, as in yours. – Kirk Broadhurst Jan 19 '11 at 03:01
2

You can get hold of Linq-to-SQL's internal change tracker using reflection. Not pretty, but it works unless your app is running with limited trust. See the following threads for samples:

What's the cleanest way to make a Linq object "dirty"?
Can you convince a DataContext to treat a column as always dirty?

Community
  • 1
  • 1
KristoferA
  • 12,287
  • 1
  • 40
  • 62
  • Nice! Well, sort of :) Not clean but that solves the problem and is even more flexible because I can hook that to the `XElement.Changed` event. – Xavier Poinas Jan 19 '11 at 22:12
1

The problem here is that altering the value of the XML column doesn't mark it as 'changed' - the reference doesn't change, so the mapper doesn't know that it has changed.

The answer is surprisingly simple:

var field = new XElement(myEntity.MyXmlField);
field.Add(new XAttribute("attribute", "value")); 
myEntity.MyXmlField = field;
Kirk Broadhurst
  • 27,836
  • 16
  • 104
  • 169
  • This will not work because in the setter generated by the LinqToSql designer, there is that check: `if (this._Responses != value) { ... }`. So setting the property to the same object reference will have no effect. – Xavier Poinas Jan 19 '11 at 02:27
  • Yes you are correct, I haven't done this for a while and forget. Editing to fix now... – Kirk Broadhurst Jan 19 '11 at 02:39