4

I'm using Entity Framework with MySQL. Suppose I have the following entities:

  • Country
    • State
      • City
        • Car
        • Building

To eagerly include all the way down to Cars, I can use the following:

context.Countries.
    Include(c => c.States.Select(s => s.Cities.Select(ci => ci.Cars))).ToList();

Similarly, to include all the way down to Buildings, I can use:

context.Countries.
    Include(c => c.States.Select(s => s.Cities.Select(ci => ci.Buildings))).ToList();

They both work just fine. Now, I would like to combine these two in order to include both Cars and Buildings, so I do the following:

context.Countries.
    Include(c => c.States.Select(s => s.Cities.Select(ci => ci.Cars))).
    Include(c => c.States.Select(s => s.Cities.Select(ci => ci.Buildings))).ToList();

But whenever I combine the two together --using the above code--, it throws an EntityCommandExecutionException exception with the following message in the inner exception:

{"Unknown column 'Apply1.Id' in 'field list'"}

I spent two hours trying to figure out what's wrong with the query, and finally, I decided to test it with SQL Server and it worked without any problems.

To sum up my questions:

  • Any idea why this doesn't work with MySQL? And Is there something wrong with the query itself?
  • Is there any workaround/alternative to achieve this with MySQL?

Please note that this only happens at the third level (the second level of Select), for example, the following would work just fine:

context.Countries.
    Include(c => c.States.Select(s => s.Cities.Select(ci => ci.Cars))).
    Include(c => c.States.Select(s => s.Laws.Select(l => l.PrivacyLaws))).ToList();

Here's the full exception details in case it's relevant:

System.Data.Entity.Core.EntityCommandExecutionException was unhandled
  HResult=-2146232004
  Message=An error occurred while executing the command definition. See the inner exception for details.
  Source=EntityFramework
  StackTrace:
       at System.Data.Entity.Core.EntityClient.Internal.EntityCommandDefinition.ExecuteStoreCommands(EntityCommand entityCommand, CommandBehavior behavior)
       at System.Data.Entity.Core.Objects.Internal.ObjectQueryExecutionPlan.Execute[TResultType](ObjectContext context, ObjectParameterCollection parameterValues)
       at System.Data.Entity.Core.Objects.ObjectQuery`1.<>c__DisplayClass7.<GetResults>b__6()
       at System.Data.Entity.Core.Objects.ObjectContext.ExecuteInTransaction[T](Func`1 func, IDbExecutionStrategy executionStrategy, Boolean startLocalTransaction, Boolean releaseConnectionOnSuccess)
       at System.Data.Entity.Core.Objects.ObjectQuery`1.<>c__DisplayClass7.<GetResults>b__5()
       at System.Data.Entity.Infrastructure.DefaultExecutionStrategy.Execute[TResult](Func`1 operation)
       at System.Data.Entity.Core.Objects.ObjectQuery`1.GetResults(Nullable`1 forMergeOption)
       at System.Data.Entity.Core.Objects.ObjectQuery`1.<System.Collections.Generic.IEnumerable<T>.GetEnumerator>b__0()
       at System.Data.Entity.Internal.LazyEnumerator`1.MoveNext()
       at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
       at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
       at ConsoleApplication1.Program.Main(String[] args) in E:\Test\tmpEF\tmpEF\Program.cs:line 15
       at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
       at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()
  InnerException: 
       ErrorCode=-2147467259
       HResult=-2147467259
       Message=Unknown column 'Apply1.Id' in 'field list'
       Number=1054
       Source=MySql.Data
       StackTrace:
            at MySql.Data.MySqlClient.MySqlStream.ReadPacket()
            at MySql.Data.MySqlClient.NativeDriver.GetResult(Int32& affectedRow, Int64& insertedId)
            at MySql.Data.MySqlClient.Driver.GetResult(Int32 statementId, Int32& affectedRows, Int64& insertedId)
            at MySql.Data.MySqlClient.Driver.NextResult(Int32 statementId, Boolean force)
            at MySql.Data.MySqlClient.MySqlDataReader.NextResult()
            at MySql.Data.MySqlClient.MySqlCommand.ExecuteReader(CommandBehavior behavior)
            at MySql.Data.Entity.EFMySqlCommand.ExecuteDbDataReader(CommandBehavior behavior)
            at System.Data.Common.DbCommand.ExecuteReader(CommandBehavior behavior)
            at System.Data.Entity.Infrastructure.Interception.DbCommandDispatcher.<Reader>b__c(DbCommand t, DbCommandInterceptionContext`1 c)
            at System.Data.Entity.Infrastructure.Interception.InternalDispatcher`1.Dispatch[TTarget,TInterceptionContext,TResult](TTarget target, Func`3 operation, TInterceptionContext interceptionContext, Action`3 executing, Action`3 executed)
            at System.Data.Entity.Infrastructure.Interception.DbCommandDispatcher.Reader(DbCommand command, DbCommandInterceptionContext interceptionContext)
            at System.Data.Entity.Internal.InterceptableDbCommand.ExecuteDbDataReader(CommandBehavior behavior)
            at System.Data.Common.DbCommand.ExecuteReader(CommandBehavior behavior)
            at System.Data.Entity.Core.EntityClient.Internal.EntityCommandDefinition.ExecuteStoreCommands(EntityCommand entityCommand, CommandBehavior behavior)
       InnerException: 
  • 2
    (1) Nothing wrong with your query (2) Of course it's a MySQL provider bug. Reported as [#78798](https://bugs.mysql.com/bug.php?id=78798) and looks like no one cares to reproduce and fix it (3) Workaround... well, good luck. – Ivan Stoev Apr 24 '18 at 18:55
  • @IvanStoev Thank you for finding this. I just provided them with a complete repeatable test case as they had asked. Hope it gets resolved soon. – 41686d6564 stands w. Palestine Apr 24 '18 at 23:52
  • Why not you try EF Core for multiple level include through ThenInclude() function. check this out http://entityframework.net/include-multiple-levels – Muhammad Imran khan Apr 25 '18 at 09:45

1 Answers1

3

As @IvanStoev points out this already is a Reported Bug, but a better question is why do you call a query that produces cartesian production. Its usually not a good Idea to include multiple data set from entityframework. I.E

context.Countries.
    Include(c => c.States.Select(s => s.Cities.Select(ci => ci.Cars))).
    Include(c => c.States.Select(s => s.Cities.Select(ci => ci.Buildings))).ToList();

this query will pull back a data set in it, for every 1 Building you have every possible car and include the city Information. You are vastly wasting resources. Instead you should load the collections seperate, this will avoid the bug. and load your related entities with minimal overhead. Optimally you should call this, which will also work as a Work Around:

//You probably want to filter to the countries that have states
var countriesQuery = context.Countries.AsQueryable();
var statesQuery = countriesQuery.SelectMany(x => x.States);
statesQuery.Load();

var cityQuery = statesQuery.SelectMany(x => x.Cities);
cityQuery.Load();
cityQuery.SelectMany(x => x.Cars).Load();
cityQuery.SelectMany(x => x.Buildings).Load();
return countriesQuery.ToArray()

You may make the decision to load say states with the countries in the include, but you shouldn't pile on nested many to many because it can grow in magnitude

johnny 5
  • 19,893
  • 50
  • 121
  • 195
  • Wow, this is very interesting, I didn't know about the `Load` method. It actually works, but I'm still having a hard time understanding how this uses fewer resources compared to using `Include` and `Select`. For example, I can still call `returntedCountries.First().States.First().Cities.First().Cars.First().Id`, right? What difference does it make? Can you please elaborate on this part. – 41686d6564 stands w. Palestine Apr 27 '18 at 06:14
  • Never mind, I get it now. Both your explanation and [this question](https://stackoverflow.com/q/19319116/4934172) helped me understand. Thanks a million :) – 41686d6564 stands w. Palestine Apr 27 '18 at 06:23
  • @AhmedAbdelhameed I’m glad I can be of help let me know if you have any other questions – johnny 5 Apr 27 '18 at 12:34