I have a query that is dynamically generated for the purpose of searching a rather large set of records. I am using MySQL Connector/NET 6.8.3 via a NuGet package with Entity Framework 6. The Expression
which is executed inside the Where
is built programmatically.
For an explanation of the problem I am seeing, I have a record which has many detail records. My filter generates the following expression (this is the output from Expression.ToString()
):
Expression<Func<DB.record, bool>> filter = t => t.details
.Where(d => (d.value== value(Filters.ContainsValueFilter).Value))
.Any()
So, the query is first executed like so to get me a record count (for my pagination):
context.records.Where(filter).Count();
This works just fine. However, when I do the next query things fall apart:
context.records.Where(filter)
.OrderByDescending(t => t.transaction_time)
.Skip(page * pageSize) //page and pageSize are ints
.Take(pageSize)
.ToList();
This query throws a NotImplementedException
(inside a System.Data.Entity.Core.EntityCommandCompilationException
) which occurs here:
at MySql.Data.Entity.SelectStatement.Accept(SqlFragmentVisitor visitor)
at MySql.Data.Entity.ExistsFragment.Accept(SqlFragmentVisitor visitor)
at MySql.Data.Entity.SqlGenerator.VisitAndReplaceTableName(SqlFragment sf, String oldTable, String newTable)
at MySql.Data.Entity.SqlGenerator.FuseSelectWithInnerSelect(SelectStatement outer, SelectStatement inner)
at MySql.Data.Entity.SqlGenerator.TryFusingSelect(InputFragment f)
at MySql.Data.Entity.SqlGenerator.VisitInputExpression(DbExpression e, String name, TypeUsage type)
at MySql.Data.Entity.SelectGenerator.VisitInputExpressionEnsureSelect(DbExpression e, String name, TypeUsage type)
at MySql.Data.Entity.SelectGenerator.Visit(DbLimitExpression expression)
at System.Data.Entity.Core.Common.CommandTrees.DbLimitExpression.Accept[TResultType](DbExpressionVisitor`1 visitor)
at MySql.Data.Entity.SqlGenerator.VisitInputExpression(DbExpression e, String name, TypeUsage type)
at MySql.Data.Entity.SelectGenerator.VisitInputExpressionEnsureSelect(DbExpression e, String name, TypeUsage type)
at MySql.Data.Entity.SelectGenerator.Visit(DbProjectExpression expression)
at System.Data.Entity.Core.Common.CommandTrees.DbProjectExpression.Accept[TResultType](DbExpressionVisitor`1 visitor)
at MySql.Data.Entity.SelectGenerator.GenerateSQL(DbCommandTree tree)
at MySql.Data.MySqlClient.MySqlProviderServices.CreateDbCommandDefinition(DbProviderManifest providerManifest, DbCommandTree commandTree)
at System.Data.Entity.Core.Common.DbProviderServices.CreateDbCommandDefinition(DbProviderManifest providerManifest, DbCommandTree commandTree, DbInterceptionContext interceptionContext)
at System.Data.Entity.Core.Common.DbProviderServices.CreateCommandDefinition(DbCommandTree commandTree, DbInterceptionContext interceptionContext)
at System.Data.Entity.Core.EntityClient.Internal.EntityCommandDefinition..ctor(DbProviderFactory storeProviderFactory, DbCommandTree commandTree, DbInterceptionContext interceptionContext, IDbDependencyResolver resolver, BridgeDataReaderFactory bridgeDataReaderFactory, ColumnMapFactory columnMapFactory)
My Question:
What causes this? I have a copy of the MySQL Connector/NET source code that I have been looking at and I see this:
internal override void Accept(SqlFragmentVisitor visitor)
{
throw new System.NotImplementedException();
}
What am I doing wrong to even call this method? Why can't it handle a query with an Any
inside a Where
that then does OrderByDescending
, Skip
, and Take
? That seems like a perfectly reasonable query to me (and I could write out the SQL easily...its an ORDER BY
followed by a LIMIT X,Y
after a WHERE
which contains an EXISTS
).
This has happened to me quite a bit and while I have generally found ways to get around this (and will probably end up doing the same here again), I am just getting frustrated always running in to this when I need to executed a simple query (generally involving an Any
inside a Where
).