views:

37

answers:

2

I'm getting this error:

Only parameterless constructors and initializers are supported in LINQ to Entities.

When trying to run this code (found this code here and made test database to play around with):

XElement xml = new XElement("contacts",
                    from c in db.Contacts
                    orderby c.ContactId
                    select new XElement("contact",
                              new XAttribute("contactId", c.ContactId),
                              new XElement("firstName", c.FirstName),
                              new XElement("lastName", c.LastName))
                    );

where db is the auto created entities object. Any ideas on how to get this to work?

+1  A: 

I believe it's objecting to the fact that you're using an XElement constructor that takes parameters in your "select" clause. Since XElement doesn't have a parameterless constructor, you might need to change your code to select an anonymous type, and initialize the XElement collection after the fact.

var els = from c in db.Contacts
          orderby c.ContactID
          select new { c.ContactID, c.FirstName, c.LastName };

var xml = new XElement("contacts",
    els.ToList()
       .Select(e => new XElement("contact", 
                        new XAttribute("contactID", e.ContactID),
                        new XElement("firstName", e.FirstName),
                        new XElement("lastName", e.LastName))));

That's untested, but hopefully gives you the idea. I'm doing the EF query first, and then calling ToList() on it so that I can select the XElement collection using Linq to Objects rather than EF.

Matt Hamilton
Thanks! That works which is the important part :)! I'm still sorta confused about why the original code didn't work though, I've seen other similar examples creating XML documents. Any ideas?
evan
By the error, it seems that EF just doesn't support selecting objects that don't have parameterless ctors. I don't know why this limitation exists, but yes, pulling the EF query out of the equation solves the problem.
Matt Hamilton
A: 

I would rewrite it like this:

XElement xml2 = new XElement("contacts", 
                    from c in
                    ((IEnumerable<Contact>)(from c in Contacts
                    orderby c.ContactId
                    select c))
                select new XElement("contact", 
                      new XAttribute("contactId", c.ContactId),
                      new XElement("firstName", c.FirstName),
                      new XElement("lastName", c.LastName))
            );

The point is to separate LINQ execution tree from XElement instantiation. By casting LINQ query from IQueriable to IEnumerable, you will separate code LINQ will use to get data from code that is going to create your XElements.

TTRider