Esteban Araya
Esteban Araya

Reputation: 29664

Encapsulating LINQ select statement

I have LINQ statement that looks like this:

return ( from c in customers select new ClientEntity() { Name = c.Name, ... });

I'd like to be able to abstract out the select into its own method so that I can have different "mapping" option. What does my method need to return?

In essence, I'd like my LINQ query to look like this:

return ( from c in customers select new Mapper(c));

Edit:

This is for LINQ to SQL.

Upvotes: 2

Views: 4138

Answers (4)

Tomas Petricek
Tomas Petricek

Reputation: 243041

BTW: The solutions described here will work only if you want to use the 'factored' part of the code in a separate query clause (e.g. Select). If you'd like to use it as part of a clause that also does some other thing (perhaps return anonymous type with some other information), you'll need to construct the whole expression tree dynamically using Expression.Xyz methods.

Alternatively you could use the trick for embedding lambda expressions that I described here:

Upvotes: 0

bdukes
bdukes

Reputation: 155915

You might have to use chained methods instead of using LINQ syntax, and then you'll be able to pass in any of a variety of Expression<Func<TSource, TResult>> values that you specify:

Expression<Func<CustomerTable, Customer>> someMappingExpression = c => new Customer { Name = c.Name };
return context.CustomerTable.Select(someMappingExpression);

UPDATE: Select takes a Func, not an Expression
UPDATE: The Select function that should be used does take an Expression<Func>, rather than just a Func.

Upvotes: 1

Daniel Earwicker
Daniel Earwicker

Reputation: 116654

New answer now I've noticed that it's Linq to SQL... :)

If you look at the version of Select that works on IQueryable<T> it doesn't take a Func<In, Out>. Instead, it takes an Expression<Func<In, Out>>. The compiler knows how to generate such a thing from a lambda, which is why your normal code compiles.

So to have a variety of select mapping functions ready to use by passing them to Select, you could declared them like this:

private static readonly Expression<Func<CustomerInfo, string>> GetName = c => c.Name;

private static readonly Expression<Func<CustomerInfo, ClientEntity>> GetEntity = c => new ClientEntity { Name = c.Name, ... };

You would then use them like this:

var names = customers.Select(GetName);

var entities = customers.Select(GetEntity);

Upvotes: 4

Frans Bouma
Frans Bouma

Reputation: 8357

This is for linq to objects? Or for a linq to ?

Because ... select new Mapper(c), requires that 'c' is already materialized into an object, and then passed to the Mapper() CTor. (as 'c' is not known at the db level, only at the .NET level)

Upvotes: 0

Related Questions