Avoiding duplicate code in Linq Select method

I have some stupid situation where I can't find simple and elegant solution for annoying problem.

I writing asp.net application with simple UI for querying database based on user choices. For querying DB I using Entity Framework.

In my scenario, one of the optional user choices is a free text, and for that I using SQL Server FTS capabilities (using CONTAINSTABLE function, since I need to order results by relevance).

Now, I have the following situation:

If user did not provided free text criteria, I creating simple Linq query with result of type IQueriable<Result> (where 'Result' is an entity with data from table)

But, if user did provided free text criteria, I creating query with CONTAINSTABLE, and its type is IQueriable<ResultWithRank> (where 'ResultWithRank' is a object contains two entities: 'Result' and 'Rank', since CONTAINSTABLE results in inner join).

At this stage, after I built my queriable, I need to execute 'Select' method on it, in order to convert it to something useful.

Here is the problem:

In first case, my select statement looks like this:

var result = queryable.Select(entity => /*.. about 20 lines of reshapying code .. */

In second case, it looks like this:

var result = queryable.Select(entity.Result => /*.. about 20 lines of exactly the same reshapying code .. */

I want to avoid duplication of "select" code, because it identical for both cases. I tried to move it to external method, but this was failing to execute, since Linq was trying to convert my method to SQL and obviously failed.

How I can resolve this problem in some elegant way, without duplicating 'select' code?

Jon Skeet
people
quotationmark

I'd use:

Expression<Func<Result, Foo>> conversion = result => { ... };

First case:

var result = queryable.Select(conversion);

Second case:

var result = queryable.Select(entity => entity.Result)
                      .Select(conversion);

Basically use the fact that you can perform two projections together, so that your first projection (in the second case) gets you into a situation you've already tackled.

people

See more on this question at Stackoverflow