locked
LINQ to Entites 'parameterless constructor' error RRS feed

  • Question

  • Hello,

    My web application was using Linq to Sql Classes and we're now changing to the Ado.Net entity model. However, the following test query gave us a NotSupportedException.

    1IEnumerable<ItemDetails> cart = from ca in context.tb_carts 
    2           select new ItemDetails 
    3           ( 
    4               ca.tb_items.id, 
    5               ca.tb_items.name, 
    6               ca.tb_items.description, 
    7               ca.tb_items.tb_item_categories.name, 
    8               ca.tb_items.price 
    9           ); 
    10 
    11foreach(ItemDetails i in cart) 
    12
    13    ... 
    14


    We get a runtime error at line 11: "Only parameterless constructors and initializers are supported in LINQ to Entities."

    This was working perfectly in Linq to Sql. It does work if IEnumerable<ItemDetails> was changed to the anonymous type 'var', but we do not desire this, mostly because we want a function to return the IEnumerable. I read in some other question to replace 'context.tb_carts' in line 1 with 'context.tb_carts.ToList()' but that gave  us a NullExceptionError in lines 2-9, besides that no explanation was given to why that should be done.

    Any possible solutions to this or reasons for this happening?
    Any help will be greatly appreciated
    Thanks in advance



    ABC
    Friday, March 20, 2009 7:23 PM

Answers

  • LINQ to Entities takes a different approach than LINQ to SQL in some areas.  In part this is a matter of wanting LINQ to Entities to be more explicit about the boundary between what parts of your query execute on the server and what part execute on the client. 

    With LINQ to SQL, for instance, it is possible to write a LINQ query which not only involves data from the server and functions on the server but also functions that can only be executed on the client and to mix them in together.  The LINQ to SQL provider will then do its best to untangle things and execute the parts that it can on the server and other parts on the client.  This is nice because it is easy to just write whatever query you want and if at all possible it will work.  On the other hand, it's not so nice if you accidentally write a query where the only part which can execute on the server is the most basic thing that returns all the data in one or more tables and then have all the filtering happen on the client (with very nasty perf consequences).

    With LINQ to Entities, the boundaries are more explicit.  When you write a LINQ query against a LINQ to Entities IQueryable implementation, the entire query executes on the server, and if some part of the query cannot be executed on the server, then an explicit boundary must be created with something like ToQueryable() or ToList().  Once that query is executed and the data retrieved, then you can use LINQ to Objects to further refine the query if you so choose.  This way you explicitly know where your boundaries are, and it's easier to track down performance issues and the like.  One of the related limitations is that the select statement in LINQ to Entities can create anonymous types or other types as long as they have a default constructor and settable parameters.  This minimizes the chance that the select statement has major side effects.

    As mentioned above, if you need to construct something which does not fit these constraints, then your best option is probably to have your linq to entities query return an anonymous type, and then wrap that with a linq to objects query which extracts the values from that type and calls the constructor on your other type:

    var serverQuery = from ca in context.tb_carts
                              select new
                              {
                                  ID = ca.tb_items.id,
                                  Name = ca.tb_items.name,
                                  Description = ca.tb_items.description,
                                  CategoryName = ca.tb_items.tb_item_categories.name,
                                  Price = ca.tb_items.price
                              };
    IEnumerable<ItemDetails> cart = from ca in serverQuery.AsEnumerable()
                                                    select new ItemDetails
                                                    (
                                                        ca.ID,
                                                        ca.Name,
                                                        ca.Description,
                                                        ca.CategoryName,
                                                        ca.Price
                                                    );
    - Danny

    This posting is provided "AS IS" with no warranties, and confers no rights.
    Wednesday, April 1, 2009 1:36 AM

All replies

  • I don't see in your example above where are u doing assignment to properties on the ItemDetails entity but u may want to consider reading this to see if u are encountering this issue.

    http://weblogs.asp.net/zeeshanhirani/archive/2008/06/14/use-default-constructors-for-query-continuation.aspx

    Thanks
    Zeeshan Hirani
    Friday, March 20, 2009 7:53 PM
  • Thank you for your quick, helpful response.

    Regarding your first part, ItemDetails has a constructor that takes the given values as parameters. The suggestion in the page you linked me too did work correctly for me, although for that to work, the properties of the class ItemDetails had to have a setter too. While this is somewhat acceptable, it'd be slightly better if I could leave the properties as read only.

    But once again, thank you.
    Friday, March 20, 2009 8:41 PM
  • Hi *,

    hum, see your point. I think the best way will be to create anonymous object with values for your ItemDetails and then create another IEnumerable with this converted to ItemDetails. You can create generic wrapper for enumerating, with function to be able re-shape data, so you'll be able to reuse it.


    Jiri {x2} Cincura
    Saturday, March 21, 2009 6:49 PM
  • LINQ to Entities takes a different approach than LINQ to SQL in some areas.  In part this is a matter of wanting LINQ to Entities to be more explicit about the boundary between what parts of your query execute on the server and what part execute on the client. 

    With LINQ to SQL, for instance, it is possible to write a LINQ query which not only involves data from the server and functions on the server but also functions that can only be executed on the client and to mix them in together.  The LINQ to SQL provider will then do its best to untangle things and execute the parts that it can on the server and other parts on the client.  This is nice because it is easy to just write whatever query you want and if at all possible it will work.  On the other hand, it's not so nice if you accidentally write a query where the only part which can execute on the server is the most basic thing that returns all the data in one or more tables and then have all the filtering happen on the client (with very nasty perf consequences).

    With LINQ to Entities, the boundaries are more explicit.  When you write a LINQ query against a LINQ to Entities IQueryable implementation, the entire query executes on the server, and if some part of the query cannot be executed on the server, then an explicit boundary must be created with something like ToQueryable() or ToList().  Once that query is executed and the data retrieved, then you can use LINQ to Objects to further refine the query if you so choose.  This way you explicitly know where your boundaries are, and it's easier to track down performance issues and the like.  One of the related limitations is that the select statement in LINQ to Entities can create anonymous types or other types as long as they have a default constructor and settable parameters.  This minimizes the chance that the select statement has major side effects.

    As mentioned above, if you need to construct something which does not fit these constraints, then your best option is probably to have your linq to entities query return an anonymous type, and then wrap that with a linq to objects query which extracts the values from that type and calls the constructor on your other type:

    var serverQuery = from ca in context.tb_carts
                              select new
                              {
                                  ID = ca.tb_items.id,
                                  Name = ca.tb_items.name,
                                  Description = ca.tb_items.description,
                                  CategoryName = ca.tb_items.tb_item_categories.name,
                                  Price = ca.tb_items.price
                              };
    IEnumerable<ItemDetails> cart = from ca in serverQuery.AsEnumerable()
                                                    select new ItemDetails
                                                    (
                                                        ca.ID,
                                                        ca.Name,
                                                        ca.Description,
                                                        ca.CategoryName,
                                                        ca.Price
                                                    );
    - Danny

    This posting is provided "AS IS" with no warranties, and confers no rights.
    Wednesday, April 1, 2009 1:36 AM