Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

LINQ to SQL Projection: Func vs Inline

I am finding some unexpected behavior when using a projection in a LINQ to SQL query using a Func. Example code will explain better than words.

A basic L2S lambda query using projection:

db.Entities.Select(e => new DTO(e.Value));

It translates to the desired SQL:

SELECT [t1].[Value]
FROM [Entity] AS [t1]

However, when the projection is put into a Func like this:

Func<Entity, DTO> ToDTO = (e) => new DTO(e.Value);

And called like this:

db.Entities.Select(e => ToDTO(e));

The SQL is now pulling back all of the columns in the table, not just the one in the projection:

SELECT [t1].[Id], [t1].[Value], [t1].[timestamp], [t1].[etc...]
FROM [Entity] AS [t1]

So my question is, how do I encapsulate this projection without the LINQ to SQL instantiating the whole Entity?

Things to keep in mind, the DTO I am using has a protected default constructor, so I can't use an object initializer. And since the DTO class cannot be modified, I'd have to make a subclass to implement that behavior. Which is fine, if that's the only solution.

Thanks.

Edit:

Thanks to Brian for the solution. I had previously tried an Expression but couldn't figure out the syntax. Here's the working code:

Expression<Entity, DTO> ToDTO = (e) => new DTO(e.Value);

Then call it like this:

db.Entities.Select(ToDTO);

At first I was trying to call it like this, which wouldn't compile. This is the proper syntax for calling a Func, but not an Expression.

db.Entities.Select(e => ToDTO(e));
like image 233
mikesigs Avatar asked Jan 13 '11 17:01

mikesigs


1 Answers

You probably need to create an Expression, not a Func

Expression<Func<Entity, DTO>> ToDTO = (e) => new DTO(e.Value);

IQueryable extension methods work with Expressions, not Funcs

By passing in a Func, you are probably invoking the IEnumerable extension method, which is why Linq2Sql is acting the way it is.

like image 118
Brian Ball Avatar answered Nov 02 '22 10:11

Brian Ball