C# – LINQ Dynamic Where – Not adding clause

clinq

I have the following code:

public OTestTable GetTestCode(Func<TestTable, bool> whereClause)
{
    return CoreContext.TestTables.Where(whereClause).Select(TestTableMap.DataToObject).FirstOrDefault();
}

CoreContext is my data context (which is initialized in a base class)

My TestTableMap is as follows:

public class TestTableMap
{
    public static readonly Func<TestTable, OTestTable> DataToObject = mapper =>
       new OTestTable
       {
           Code = mapper.mycode 

       };
}

Then in my business method i have the following:

public OTestTable GetTestCode(string code)
{
    return QueryEngine.GetTestCode(id => id.mycode == code);
}

From my main program, i am calling GetTestCode with a string value.

When I watch SQL profiler, I get the following:

SELECT [t0].[mycode]
FROM [dbo].[TestTable] AS [t0]

It does not have the where clause appended to the SQL query. If i add the where clause to the LINQ as var query = from c in DataContext.TestTable where c.mycode == '' select c;

It will add the where clause.

However, when I run my code, it will return the correct record, but it seems like I am pulling back all records from the database and filtering in my code (which should not happen).

Any thoughts with what I am doing wrong?

Thanks

Best Answer

In order to construct SQL statements, LINQ to SQL requires an expression tree. Func<TestTable, bool> does not represent an expression tree, it is a "black box" function pointer. LINQ cannot do anything intelligent with this apart from blindly execute it on an in-memory collection.

You need to do this instead:

public OTestTable GetTestCode(Expression<Func<TestTable, bool>> whereClause) {
    return CoreContext.TestTables.Where(whereClause).Select(TestTableMap.DataToObject).FirstOrDefault();
}

This code compiles using the Queryable.Where extension method, which does accept an expression tree, rather than the Enumerable.Where extension method, which only accepts a raw delegate.