1

Closed

Unable to cast Anonymous Type from 'System.Linq.IQueryable' to 'System.Data.Entity.Core.Objects.ObjectQuery'

description

After posting a question at StackOverflow about my issue, some user suggest me to post the error here.

The following query was working well with EF5 but gives me error with EF6. I use DbContext and CodeFirst.

Error raised with EF6:

Unable to cast the type 'System.Linq.IQueryable1[[<>f__AnonymousType54[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], Wms.Domain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=85d69d39f5becc93]]' to type 'System.Data.Entity.Core.Objects.ObjectQuery1[[<>f__AnonymousType54[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], Wms.Domain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=85d69d39f5becc93]]'. LINQ to Entities only supports casting EDM primitive or enumeration types.

Query (simplified):

var unitsPerPosition = context.Positions.Include(p => p.Unit).Select(x => new { Unit = x.Unit, Position = x });

var orders = (
                from order in context.Orders.Include(x => x.SourceLocation);
                join unitPosition in unitsPerPosition on order.UnitId equals unitPosition.Unit.UnitId
                group new { order, unitPosition } by new { LocationId = order.SourceLocationId, Level = unitPosition.Position.Level } into groupOrders
                where groupOrders.Key.LocationId != null
                select new { 
                    LocationId = groupOrders.Key.LocationId.Value, 
                    Level = groupOrders.Key.Level, 
                    LoadingOrders = groupOrders.Count(), 
                    UnloadingOrders = -1 }
            );

IList<LocationChannels> searchResult = (from s in context.Locations
        .Include(s => s.Positions)
        .Include(s => s.Positions.Select(sp => sp.Unit))

        let channels = from p in s.Positions
                        where p.LocationId == s.LocationId
                        group p by new { p.LocationId, p.Column, p.Level } into channelsGroup

                        join order in orders on new { channelsGroup.Key.LocationId, channelsGroup.Key.Level } 
                        equals new { order.LocationId, order.Level } into ordersGroup
                        from o in ordersGroup.DefaultIfEmpty()

                        select new Channel
                        {
                            LocationId = channelsGroup.Key.LocationId,
                            Column = channelsGroup.Key.Column,
                            Level = channelsGroup.Key.Level
                        }

        select new LocationChannels
                      {
                        Location = s,
                        Channels = channels,
                      })
    .Where(predicate).ToList();
The issue appears to be on the left join with the anonymous type loaded in variable 'orders'. I also tried to add a ToList() to the 'orders' query but then the error change to:
Unable to create a constant value of type 'Anonymous type'. Only primitive types or enumeration types are supported in this context.
Can someone gives me an hint on how to fix it?
Closed Oct 31, 2013 at 9:55 PM by lukew
Verified successfully ported to 6.0.2

comments

maumar wrote Oct 19, 2013 at 3:29 AM

Simplified repro:
namespace Repro1751
{
    using System.Collections.Generic;
    using System.Data.Entity;
    using System.Linq;

    public class Customer
    {
        public int Id { get; set; }
        public ICollection<Order> Orders { get; set; }
    }

    public class Order
    {
        public int Id { get; set; }
    }

    public class Product
    {
        public int Id { get; set; }
    }

    public class SimpleContext : DbContext
    {
        public DbSet<Customer> Customers { get; set; }
        public DbSet<Product> Products { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            using (var context = new SimpleContext())
            {
                //works (project int, rather than new { int }
                ////var products = context.Products.Select(p => p.Id);
                
                ////var result = context.Customers
                ////.Select(c =>
                ////    c.Orders
                ////    .Join(products, o => o.Id, i => i, (o, i) => new { o, i })).ToList();


                var products = context.Products.Select(p => new { p.Id });

                var result = context.Customers
                .Select(c =>
                    c.Orders
                    .Join(products, o => o.Id, i => i.Id, (o, i) => new { o, i })).ToList();
            }
        }
    }
}
Exception:


Unhandled Exception: System.NotSupportedException: Unable to cast the type 'System.Linq.IQueryable1[[<>f__AnonymousType01[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], Repro1751, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]' to type 'System.Data.Entity.Core.Objects.ObjectQuery1[[<>f__AnonymousType01[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], Repro1751, Version=1.0
.0.0, Culture=neutral, PublicKeyToken=null]]'. LINQ to Entities only supports casting EDM primitive or enumeration types.
at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.ValidateAndAdjustCastTypes(TypeUsage toType, TypeUsage fromType, Type toClrType, Type fromClrType) in d:\entityframework\src\EntityFramework\Core\Objects\ELinq\ExpressionConverter.cs:line 613
at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.GetCastTargetType(TypeUsage fromType, Type toClrType, Type fromClrType, Boolean preserveCastForD
ateTime) in d:\entityframework\src\EntityFramework\Core\Objects\ELinq\ExpressionConverter.cs:line 597
at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.CreateCastExpression(DbExpression source, Type toClrType, Type fromClrType) in d:\entityframework\src\EntityFramework\Core\Objects\ELinq\ExpressionConverter.cs:line 826
at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.ConvertTranslator.TranslateUnary(ExpressionConverter parent, UnaryExpression unary, DbExpression operand) in d:\entityframework\src\EntityFramework\Core\Objects\ELinq\Translator.cs:line 1522
at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.UnaryTranslator.TypedTranslate(ExpressionConverter parent, UnaryExpression linq) in d:\entityframework\src\EntityFramework\Core\Objects\ELinq\Translator.cs:line 1490
at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TypedTranslator1.Translate(ExpressionConverter parent, Expression linq) in d:\entityframework\src\EntityFramework\Core\Objects\ELinq\Translator.cs:line 62
at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq) in d:\entityframework\src\EntityFramework\Core\Objects\ELinq\ExpressionConverter.cs:line 984
at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TranslateSet(Expression linq) in d:\entityframework\src\EntityFramework\Core\Objects\ELinq\ExpressionConverter.cs:line 969
at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.JoinTranslator.Translate(ExpressionConverter parent, MethodCallExpression call) in d:\entityframework\src\EntityFramework\Core\Objects\ELinq\MethodCallTranslator.cs:line 1774
at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.SequenceMethodTranslator.Translate(ExpressionConverter parent, MethodCallExpression call, SequenceMethod sequenceMethod) in d:\entityframework\src\EntityFramework\Core\Objects\ELinq\MethodCallTranslator.cs:line 1698
at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.TypedTranslate(ExpressionConverter parent, MethodCallExpression linq) in d:\entityframework\src\EntityFramework\Core\Objects\ELinq\MethodCallTranslator.cs:
line 44
at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TypedTranslator
1.Translate(ExpressionConverter parent, Expression linq) in d:\entityframework\src\EntityFramework\Core\Objects\ELinq\Translator.cs:line 62
at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq) in d:\entityframework\src\EntityFramework\Core\Objects\ELinq\ExpressionConverter.cs:line 984
at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TranslateLambda(LambdaExpression lambda, DbExpression input) in d:\entityframework\src\EntityFramework\Core\Objects\ELinq\ExpressionConverter.cs:line 888
at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TranslateLambda(LambdaExpression lambda, DbExpression input, DbExpressionBinding& binding) in d:\entityframework\src\EntityFramework\Core\Objects\ELinq\ExpressionConverter.cs:line 845
at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.OneLambdaTranslator.Translate(ExpressionConverter parent, MethodCallExpression call, DbExpression& source, DbExpressionBinding& sourceBinding, DbExpression& lambda) in d:\entityframework\src\EntityFramework\Core\Objects\ELinq\MethodCallTranslator.cs:line 2412
at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.SelectTranslator.Translate(ExpressionConverter parent, MethodCallExpression call) in d:\entityframework\src\EntityFramework\Core\Objects\ELinq\MethodCallTranslator.cs:line 2474
at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.SequenceMethodTranslator.Translate(ExpressionConverter parent, MethodCallExpression call, SequenceMethod sequenceMethod) in d:\entityframework\src\EntityFramework\Core\Objects\ELinq\MethodCallTranslator.cs:line 1698
at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.TypedTranslate(ExpressionConverter parent, MethodCallExpression linq) in d:\entityframework\src\EntityFramework\Core\Objects\ELinq\MethodCallTranslator.cs:line 44
at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TypedTranslator1.Translate(ExpressionConverter parent, Expression linq) in d:\entityframework\src\EntityFramework\Core\Objects\ELinq\Translator.cs:line 62
at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq) in d:\entityframework\src\EntityFramework\Core\Objects\ELinq\ExpressionConverter.cs:line 984
at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.Convert() in d:\entityframework\src\EntityFramework\Core\Objects\ELinq\ExpressionConverter.cs:line 268
at System.Data.Entity.Core.Objects.ELinq.ELinqQueryState.GetExecutionPlan(Nullable
1 forMergeOption) in d:\entityframework\src\EntityFramework\Core\Objects\ELinq\ELinqQueryState.cs:line 120
at System.Data.Entity.Core.Objects.ObjectQuery1.<>c__DisplayClassb.<GetResults>b__a() in d:\entityframework\src\EntityFramework\Core\Objects\ObjectQuery.cs:line 734
at System.Data.Entity.Core.Objects.ObjectContext.ExecuteInTransaction[T](Func1 func, IDbExecutionStrategy executionStrategy, Boolean startLocalTransaction, Boolean releaseConnectionOnSuccess) in d:\entityframework\src\EntityFramework\Core\Objects\ObjectContext.cs:line 3186
at System.Data.Entity.Core.Objects.ObjectQuery
1.<>c__DisplayClassb.<GetResults>b__9() in d:\entityframework\src\EntityFramework\Core\Objects\ObjectQuery.cs:line 733
at System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.Execute[TResult](Func
1 operation) in d:\entityframework\src\EntityFramework.SqlServer\DefaultSqlExecutionStrategy.cs:line 52
at System.Data.Entity.Core.Objects.ObjectQuery1.GetResults(Nullable1 forMergeOption) in d:\entityframework\src\EntityFramework\Core\Objects\ObjectQuery.cs:line 732
at System.Data.Entity.Core.Objects.ObjectQuery
1.<System.Collections.Generic.IEnumerable<T>.GetEnumerator>b__0() in d:\entityframework\src\EntityFramework\Core\Objects\ObjectQuery.cs:line 571
at System.Lazy
1.CreateValue()
at System.Lazy1.LazyInitValue()
at System.Lazy
1.get_Value()
at System.Data.Entity.Internal.LazyEnumerator1.MoveNext() in d:\entityframework\src\EntityFramework\Internal\LazyEnumerator.cs:line 38
at System.Collections.Generic.List1..ctor(IEnumerable1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)

ajcvickers wrote Oct 23, 2013 at 8:37 PM

Fixed in 0d2eedf9e38e

Remember My Name (1751: Unable to cast Anonymous Type from 'System.Linq.IQueryable' to 'System.Data.Entity.Core.Objects.ObjectQuery')

This was a regression from EF5 caused by the fix to 396: Handle closures containing DbSet/DbQuery members. However, this fix wasn't really the problem, it just exposed another existing bug that would previously only manifest in less common cases. This is because the fix for 396 used the type of the IQueryable as the type of the IQueryable, whereas before the type of the expression tree was used. In the common case (anonymous projection with no casting) for this scenario the type of the expression tree was IQueryable while the type of the IQueryable was actually ObjectQuery. Later on we made the assumption that the type would be IQueryable and not ObjectQuery. This was a false assumption as sometimes the expression tree type could also be ObjectQuery (see some tests) and so this would then fail. The fix is to treat ObjectQuery, IQueryable, and IOrderedQueryable the same as far as CQT generation is concerned instead of attempting to introduce an unnecessary cast, which then fails.

maumar wrote Oct 24, 2013 at 6:45 PM

verified, closing

** Closed by maumar 10/24/2013 11:45AM

ajcvickers wrote Oct 30, 2013 at 9:42 PM

This has been merged into the 6.0.2 branch and is now ready to verify in that branch.

bradwfulton wrote Nov 8, 2013 at 11:33 PM

Is a fix imminent? Is there any way to work around this? I just converted from EF 4.4, and this issue has me stalled. I guess I could go back, but the SQL generated by V6 is sure a lot easier to parse for errors.

moozzyk wrote Nov 9, 2013 at 6:45 AM

@bradwfulton - Try a nightly build. Here are the instructions https://entityframework.codeplex.com/wikipage?title=Nightly%20Builds

jeremylew wrote Nov 21, 2013 at 2:46 PM

@ajcvickers - The change looks pretty simple. We have been hit by this, and rather than take a nightly build that has who-knows-what in it, I'm inclined to cherry-pick your commit on top of 6.0.1 and build it myself. Any reason you can think of this would be a bad idea?

Thanks