I am using the AutoMapper extensions for ASP.NET Core, so am registering Automapper at Startup like in this official example. I would like to compile mappings at startup rather letting Automapper do the default lazy compilation, but can't seem to figure out how to do eager compilation (documented here) with this setup. I tried the following, but from what I can tell it isn't causing the compilation to occur:
services.AddAutoMapper();
Mapper.Configuration.CompileMappings();
The problem I am trying to solve is that one particular mapping is rather complicated, calling multiple formatting functions, and the first hit is always very slow. I'd like to have that cost incurred when the application starts up rather than on the first map execution.
EDIT: After further investigation it seems like the performance hit comes from the EF Core compilation of the query, which lead me to try pre-compiling the query like this:
var query = EF.CompileQuery((MyProjectContext db, int id) =>
db.Product.ProjectTo<Models.Product>().FirstOrDefault()
);
var product= query(context, 1);
However, it seems ProjectTo can't be used with EF.CompileQuery, as I get this error, when I try to execute:
Test method MyProject.Test.MappingTest.ProductGetPreCompile threw exception:
System.NotSupportedException: Could not parse expression 'value(Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1[MyProject.Data.Entities.Product]).ProjectTo(value(System.Linq.Expressions.Expression`1[System.Func`2[MyProject.Web.Models.Product,System.Object]][]))': This overload of the method 'AutoMapper.QueryableExtensions.Extensions.ProjectTo' is currently not supported.
at Remotion.Linq.Parsing.Structure.MethodCallExpressionParser.GetNodeType(MethodCallExpression expressionToParse)
at Remotion.Linq.Parsing.Structure.MethodCallExpressionParser.Parse(String associatedIdentifier, IExpressionNode source, IEnumerable`1 arguments, MethodCallExpression expressionToParse)
at Remotion.Linq.Parsing.Structure.ExpressionTreeParser.ParseMethodCallExpression(MethodCallExpression methodCallExpression, String associatedIdentifier)
at Remotion.Linq.Parsing.Structure.ExpressionTreeParser.ParseNode(Expression expression, String associatedIdentifier)
at Remotion.Linq.Parsing.Structure.ExpressionTreeParser.ParseMethodCallExpression(MethodCallExpression methodCallExpression, String associatedIdentifier)
at Remotion.Linq.Parsing.Structure.ExpressionTreeParser.ParseTree(Expression expressionTree)
at Remotion.Linq.Parsing.Structure.QueryParser.GetParsedQuery(Expression expressionTreeRoot)
at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.CompileQueryCore[TResult](Expression query, INodeTypeProvider nodeTypeProvider, IDatabase database, IDiagnosticsLogger`1 logger, Type contextType)
at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.CreateCompiledQuery[TResult](Expression query)
at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQuery`2.CreateCompiledQuery(IQueryCompiler queryCompiler, Expression expression)
at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryBase`2.<>c__DisplayClass6_0.<EnsureExecutor>b__0(TContext c, LambdaExpression q)
at Microsoft.EntityFrameworkCore.Internal.NonCapturingLazyInitializer.EnsureInitialized[TParam1,TParam2,TValue](TValue& target, TParam1 param1, TParam2 param2, Func`3 valueFactory)
at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryBase`2.EnsureExecutor(TContext context)
at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryBase`2.ExecuteCore(TContext context, CancellationToken cancellationToken, Object[] parameters)
at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryBase`2.ExecuteCore(TContext context, Object[] parameters)
at MyProject.Test.MappingTest.ProductGetPreCompile() in C:\projects\MyCompany\MyCustomer\MyProject\MyProject.Test\MappingTest.cs:line 47