Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AutoMapper Project().To<T> and reusable lambda expressions

I am having a problem getting a reuasable lambda expression working with the AutoMapper Project().To extension method. I am using AutoMapper 3.1.1.

I want to be able to reuse a lambda expression by defining it as a variable, but am having issues getting this to work with the extension method.

Note the code and lambda expression shown below are simplified, my lambda expression is very complicated and I want to reuse it in a number of places.

Here is a lambda expression to reuse:

Func<Product, bool> myLambda = x => (x.Season.Id == 3);

Code Block 1 uses Project().To<> and the reusable lambda, and wont even compile.

var dtos =
                _unitOfWork.ProductRepository.All()
                    .Where(myLambda)
                    .Project().To<ProductGridDTO>()
                    .OrderBy(dynamicSort)
                    .Skip(skip)
                    .Take(take)
                    .ToList();

It gives the following compile error:

Error 18

'System.Collections.Generic.IEnumerable' does not contain a definition for 'Project' and no extension method 'Project' accepting a first argument of type 'System.Collections.Generic.IEnumerable' could be found (are you missing a using directive or an assembly reference?)

Code Block 2 uses .Select() and Mapper.Map() and compiles and works, but the SQL query generated returns all columns. I want to use Project().To<> to only return a minimal set of columns in the SQL query, and thus be more efficient and quicker.

var dtos =
                _unitOfWork.ProductRepository.All()
                    .Where(myLambda)
                    .Select(y => Mapper.Map(y, new ProductGridDTO()))
                    .OrderBy(dynamicSort)
                    .Skip(skip)
                    .Take(take)
                    .ToList();

Code Block 3 uses Project().To<> and the same lambda but as inline code. It compiles and works okay, but does not let me reuse my lambda expression.

        var dtos3 =
            _unitOfWork.ProductRepository.All()
                .Where(x => (x.Season.Id == 3))
                .Project().To<ProductGridDTO>()
                .OrderBy(dynamicSort)
                .Skip(skip)
                .Take(take)
                .ToList();

Is there any way I can get Code Block 1 working. Is there another way I can defined my lambda expression to get around this compile error?

like image 405
user3430893 Avatar asked Oct 01 '22 06:10

user3430893


1 Answers

IQueryable objects do not work with delegates, they work with Expressions. You initialize them the same way but you must declare it differently.

Expression<Func<Product, bool>> myLambda = x => (x.Season.Id == 3);

Try that out and see if it work.

The problem is because you passed in a delegate you ended up using this version of .Where( which outputs a IEnumerable, The problem is .Project<T>() requires a IQueyable<T> and to get that you must use this version of .Where( which you can see only take in a Expression<Func<TSource, bool>> not a Func<TSource, bool>.

like image 187
Scott Chamberlain Avatar answered Oct 06 '22 18:10

Scott Chamberlain