3
votes

I used the ADO.NET C# POCO Entity Generator Visual Studio add-in to generate POCO classes for my entities.

When I try to use the class in a Linq to Entities query such as the one below:

var q = from w in entities.Widgets
        select new Widget
        {
            Id = w.Id,
            WidgetName = w.WidgetName,
            WidgetDescription = w.WidgetDescription
        };


return q.ToList();

I get the following exception:

"The entity or complex type MyNamespace.Widget' cannot be constructed in a LINQ to Entities query".

The only way around this is to use an anonymous type and then another LINQ query:

var q = from w in entities.Widgets
        select new
        {
            Id = w.Id,
            WidgetName = w.WidgetName,
            WidgetDescription = w.WidgetDescription
        };

var r = from e in q.AsEnumerable()
        select new Widget
        {
            Id = e.Id,
            WidgetName = e.WidgetName,
            WidgetDescription = e.WidgetDescription
        };

return r.ToList();

This works but is pretty redundant. I understand why I'm getting the exception, but is there a more elegant way around this?

The fact that the POCO classes are generated by the ADO.NET C# POCO Entity Generator doesn't seem related to the issue; I tried using my own POCO classes and saw the same exception.

Many thanks.

EDIT: Added link to walkthrough for using the ADO.NET C# POCO Entity Generator Visual Studio add-in - http://blogs.msdn.com/b/adonet/archive/2010/01/25/walkthrough-poco-template-for-the-entity-framework.aspx

2

2 Answers

4
votes

I'm guessing MyNamespace.Widget is a custom class - and not part of the EDM?

If so, you can't project a LINQ-Entities query into a custom type. Doesn't matter if your using POCO's or not.

You've got the right idea projecting to an anonymous type.

You can shape the query on the client once you have materialized the query on the server:

var widgets = entities
               .Widgets
               .ToList() // materialize query
               .Select(x => new Widget
                       {
                          Id = w.Id,
                          WidgetName = w.WidgetName,
                          WidgetDescription = w.WidgetDescription
                       }
               ).ToList();

Which is a bit nicer than your workaround.

But this begs the question - why aren't you returning the "Widget" type on the EDM in the first place?

The whole point of POCO's is so you can seperate the persistence-logic into simple classes. So i'm not sure why your projecting from a simple type (POCO), to another (seemingly identical) simple type. Are you mapping your POCO's to DTO's for N-Tier transport?

2
votes

This page suggests that it's because you're creating an Entity object outside the scope of the Entity Framework, which is apparently not allowed. They are essentially using the same workaround as you, by double-selecting the result from the anonymous type after the initial select.

If this were me, I'd probably avoid all of this by simply selecting w and be done with it, or creating a new special View type class to accommodate for the specialisation of Widget. Hopefully there's a better answer than this :)