none
SQL Xml and LINQ serialization/deserialization RRS feed

  • Question

  • I have a column that is on the type XML. When I create an entity for this row/table and read the data in I get an XElement. Now I want to deserialize this XML to an object. If I use the XmlSerializer.Deserialize method I need an XmlReader. There seems to be lots of methods to create an XElement from an XmlReader but how do I create an object (deserialize it) it I already have an XElement?

    Thank you.

    Kevin
    Thursday, June 4, 2009 6:34 PM

Answers



  • Nesting of objects could easily be done the same way.

    Just thinking...  Though it is less linq'ish, you could also have a constructor (or factory method) on your object that takes an XElement parameter which it could take the responsibility to parse, and pass any sub elements along to the constructors of its child elements, etc.

    • Edited by Fermat8 Thursday, June 4, 2009 9:03 PM
    • Marked as answer by KevinBurton Friday, June 5, 2009 3:54 AM
    • Unmarked as answer by KevinBurton Friday, June 5, 2009 4:04 AM
    • Marked as answer by KevinBurton Friday, October 30, 2009 3:00 PM
    Thursday, June 4, 2009 9:02 PM

All replies


  • One way is to use object initializers, for example:


      var books = from b in bookXML.Elements("book")
                  select new Book
                  {
                     Title = (string)b.Element("title"),
                     Author = (string)b.Element("author"),
                     Isbn = (string)b.Element("isbn")
                  };
    


    Thursday, June 4, 2009 8:39 PM
  • Thank you. This would be a good idea for simple objects but this object that I am trying to deserialize has nested objects and in general is too compilcated to lend itself well to object initialiizers. Good suggestion though.

    Kevin
    Thursday, June 4, 2009 8:46 PM


  • Nesting of objects could easily be done the same way.

    Just thinking...  Though it is less linq'ish, you could also have a constructor (or factory method) on your object that takes an XElement parameter which it could take the responsibility to parse, and pass any sub elements along to the constructors of its child elements, etc.

    • Edited by Fermat8 Thursday, June 4, 2009 9:03 PM
    • Marked as answer by KevinBurton Friday, June 5, 2009 3:54 AM
    • Unmarked as answer by KevinBurton Friday, June 5, 2009 4:04 AM
    • Marked as answer by KevinBurton Friday, October 30, 2009 3:00 PM
    Thursday, June 4, 2009 9:02 PM
  • Another restriction that I failed to mention is that this object is in a library that cannot at this time be moved to .NET 3.5 so having a constructor taking an argument of XElement is a good idea but I don't think it will work for me right now.

    Kevin
    Friday, June 5, 2009 4:06 AM
  • The first obstacle that I encounter is one of the members is double[] so the XML looks like:

    <X><double>1</double>....</X>

    The second obstacle is that another member is a dictionary. I don't even know where to start. Simple string, double, float, or int works just fine as you illustrated.

    I can tell this is getting outside of the scope of LINQ to SQL and seems more LINQ to XML but still any help would be appreciated.

     

    Thank you.

     

    Kevin

    Friday, June 5, 2009 4:53 AM
  • Maybe this was not what LINQ was designed for but using the XmlSerializer

    string xmlString serializer.Serialize(fit);
    // Store smlString in database as a BLOB
    // Read BLOB as a string into xmlString
    ExpFit fit= (ExpFit)serializer.Deserialize(xmlString);
    

    seems alot simpler than having alot of object initializers

                            ExpFit fit = new ExpFit
                            {
                                X = new TimeSeries
                                {
                                    Title = (string)forecastData.ModelDetail.Element("X").Element("Title"),
                                    X = (double[])(forecastData.ModelDetail.Element("X").Element("X").Elements("double")),
                                    Frequency = (float)forecastData.ModelDetail.Element("X").Element("Frequency"),
                                    Start = (float[])(forecastData.ModelDetail.Element("X").Element("Start").Elements("float")),
                                    End = (float[])(forecastData.ModelDetail.Element("X").Element("End").Elements("float"))
                                },
                                Error = (ExpComponent)Enum.Parse(typeof(ExpComponent), (string)forecastData.ModelDetail.Element("Error")),
                                Trend = (ExpComponent)Enum.Parse(typeof(ExpComponent), (string)forecastData.ModelDetail.Element("Trend")),
                                Season = (ExpComponent)Enum.Parse(typeof(ExpComponent), (string)forecastData.ModelDetail.Element("Season")),
                                SeasonFrequency = (int)forecastData.ModelDetail.Element("SeasonFrequency"),
                                Alpha = (double)forecastData.ModelDetail.Element("Alpha"),
                                Beta = (double)forecastData.ModelDetail.Element("Beta"),
                                Gamma = (double)forecastData.ModelDetail.Element("Gamma"),
                                Phi = (double)forecastData.ModelDetail.Element("Phi"),
                                Ic = (double)forecastData.ModelDetail.Element("Ic"),
                                LogLik = (double)forecastData.ModelDetail.Element("LogLik"),
                                AIC = (double)forecastData.ModelDetail.Element("AIC"),
                                AICC = (double)forecastData.ModelDetail.Element("AICC"),
                                BIC = (double)forecastData.ModelDetail.Element("BIC"),
                                MSE = (double)forecastData.ModelDetail.Element("MSE"),
                                AMSE = (double)forecastData.ModelDetail.Element("AMSE"),
                                Fitted = new TimeSeries
                                {
                                    Title = (string)forecastData.ModelDetail.Element("Fitted").Element("Title"),
                                    Frequency = (float)forecastData.ModelDetail.Element("Fitted").Element("Frequency")
                                },
                                Residuals = new TimeSeries
                                {
                                    Title = (string)forecastData.ModelDetail.Element("Residuals").Element("Title"),
                                    Frequency = (float)forecastData.ModelDetail.Element("Residuals").Element("Frequency")
                                },
                                Sigma2 = (double)forecastData.ModelDetail.Element("Sigma2"),
                                InitState = (ExpDictionary<string, double>)forecastData.ModelDetail.Element("InitState")
    ....... };


    I guess I was looking for some guidance on whether I should dump LINQ in this instance and just read the "BLOB" as a string and pass it to XmlSerializer. If I use LINQ it seems that I have an XElement that obviously took some compute cycles to generate. I just wanted the process to be as efficient as possible.

    Thank you for your comments.
    Friday, June 5, 2009 6:13 PM