6 Replies - 4084 Views - Last Post: 04 February 2013 - 12:25 PM Rate Topic: -----

#1 pokiaka  Icon User is offline

  • D.I.C Head
  • member icon

Reputation: 10
  • View blog
  • Posts: 76
  • Joined: 05-August 11

Why "Only parameterless constructors and initializers are supporte

Posted 04 February 2013 - 04:47 AM

This is the original code.
It exports blog articles to XML. The articles have a default constructor ("parameterless") and they have 3 fields which are ArticleId, Title and Content.

    [HttpGet]
    public ActionResult ExportXML()
    {
        var articles = new XElement("Articles",
            from article in _provider.Articles
            select new XElement("Article", new XAttribute("ArticleId", article.ArticleId),
                new XElement("Title", article.Title),
                new XElement("Content", article.Content))
            );

        var document = new XDocument(new XDeclaration("1.0", "utf-8", "true"), articles);
        return Content(document.ToString(), MIME.Text.Xml);
    }


It threw:

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

(All of my classes have a default/parameterless constructor).

There have been a few questions in SO for this exception but they didn't answer my question nor provided a solution. I found out the solution by messing a bit with the code and I found that when you invoke ToList() on _provider.Articles at the end of the first line inside the block it fixes the problem, but I don't understand why or what is the cause for the exception in the first place, and that is my question.

_provider.Articles is of type IQueryable<Article> that is retrieving data from a DbSet<Article> in a class that derives from DbContext. In this case it connects to a local database file.

Is This A Good Question/Topic? 0
  • +

Replies To: Why "Only parameterless constructors and initializers are supporte

#2 sepp2k  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 2151
  • View blog
  • Posts: 3,306
  • Joined: 21-June 11

Re: Why "Only parameterless constructors and initializers are supporte

Posted 04 February 2013 - 05:11 AM

*
POPULAR

The error message doesn't tell you that your classes have to have a parameterless constructor - it's telling you that you're only allowed to use parameterless constructors (or initializers) in a LINQ to Entities query. So new XElement(foo, bar) is not allowed inside a Linq2Entities query because it's calling a constructor that takes 2 parameters, not zero.

When you add the ToList it works because now you're using LINQ to Objects instead of LINQ to Entities, and LINQ to Objects does not have such a restriction.
Was This Post Helpful? 5
  • +
  • -

#3 pokiaka  Icon User is offline

  • D.I.C Head
  • member icon

Reputation: 10
  • View blog
  • Posts: 76
  • Joined: 05-August 11

Re: Why "Only parameterless constructors and initializers are supporte

Posted 04 February 2013 - 06:24 AM

View Postsepp2k, on 04 February 2013 - 05:11 AM, said:

The error message doesn't tell you that your classes have to have a parameterless constructor - it's telling you that you're only allowed to use parameterless constructors (or initializers) in a LINQ to Entities query. So new XElement(foo, bar) is not allowed inside a Linq2Entities query because it's calling a constructor that takes 2 parameters, not zero.

When you add the ToList it works because now you're using LINQ to Objects instead of LINQ to Entities, and LINQ to Objects does not have such a restriction.


Ah!
Thank you very much.
Was This Post Helpful? 0
  • +
  • -

#4 Skydiver  Icon User is online

  • Code herder
  • member icon

Reputation: 3650
  • View blog
  • Posts: 11,420
  • Joined: 05-May 12

Re: Why "Only parameterless constructors and initializers are supporte

Posted 04 February 2013 - 07:27 AM

sepp2k response is very insightful. +1!

This has me very puzzled though. One of the original selling points of LINQ was that it was suppose to let the compiler catch errors like mismatched types and invalid operations in queries during compile time, unlike SQL where you only find the error at execution time. With the exception being thrown above, it looks like are now back again to having to also guard against run time errors due to incorrect construction of a query. Shouldn't there have been a syntax error if it the LINQ provider doesn't support an operation? Or are there only provisions for a LINQ provider to be called during runtime, but not during compile time?
Was This Post Helpful? 1
  • +
  • -

#5 sepp2k  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 2151
  • View blog
  • Posts: 3,306
  • Joined: 21-June 11

Re: Why "Only parameterless constructors and initializers are supporte

Posted 04 February 2013 - 07:41 AM

View PostSkydiver, on 04 February 2013 - 03:27 PM, said:

Shouldn't there have been a syntax error if it the LINQ provider doesn't support an operation?


That would be nice, yes, but the C# compiler has no knowledge of what a LINQ provider does and doesn't support.

Quote

Or are there only provisions for a LINQ provider to be called during runtime, but not during compile time?


Exactly. The processing of a query's AST by the LINQ provider happens at runtime. And since there's no compile-time information about what may or may not appear in a query's AST for a given provider, that runtime processing will be the first occasion where someone has the necessary information to realize that a given construct is not supported.

It's a bit unfortunate and you're right that it kind of runs counter to LINQ's goals, but that's the way it is.
Was This Post Helpful? 0
  • +
  • -

#6 Skydiver  Icon User is online

  • Code herder
  • member icon

Reputation: 3650
  • View blog
  • Posts: 11,420
  • Joined: 05-May 12

Re: Why "Only parameterless constructors and initializers are supporte

Posted 04 February 2013 - 08:02 AM

To me this increases the importance of unit tests even more.

At the same time, it also suddenly makes testability much harder. I can't just mock a LINQ provider by using LINQ for Objects when writing my unit tests. I'll have to ensure that my unit tests are passed LINQ providers that matches the behavior of the actual LINQ provider being using in production. In that case, I'll practically be doing integration tests rather than unit tests.

As as aside does that mean that I can't reliably apply the Liskov substitution principle for IQueryable?
Was This Post Helpful? 0
  • +
  • -

#7 AdamSpeight2008  Icon User is offline

  • MrCupOfT
  • member icon


Reputation: 2270
  • View blog
  • Posts: 9,496
  • Joined: 29-May 08

Re: Why "Only parameterless constructors and initializers are supporte

Posted 04 February 2013 - 12:25 PM

It's the LINQ Provider that does all of the work.
It decides where the "query" happens.
Does it happen locally like LINQ To Objects, or on the remote server like LINQ to SQL Server?
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1