Quantcast
Channel: Entity Framework
Viewing all articles
Browse latest Browse all 10318

Commented Issue: DbQuery to ObjectQuery replacement fails in some situations involving closures [396]

$
0
0
Current implementation of DbQueryVisitor tries to handle cases where the query is closed over variables containing DbQuery values by simply replacing them with the underlying ObjectQuery instances. Obviously, if the query is closed over a variable of type DbSet the assignment will fail.

Following code will throw System.ArgumentException: Object of type 'System.Data.Objects.ObjectQuery`1[AnyEntity]' cannot be converted to type 'System.Data.Entity.DbSet`1[AnyEntity]':

using (var anyContext = new AnyContext())
{
var anySet = anyContext.Set<AnyEntity>();

var query = from x in anyContext.Set<AnyOtherEntity>()
from y in anySet
select new { x, y };

// change the type of the anySet variable to IQueryabe and the exception is gone
// but guess what's the value of the anySet variable now
}

Also changing the value of closed variable doesn't seem right for me (simple query construction now has side effects).

Possible solution is to rewrite Constant->Field(DbSet) expression to Constant(ObjectContext) expression.
Comments: I've investigated this. We initially tried to fix by changing the line in DbQueryVisitor.VisitConstant() (where the above ArgumentException is originating from: foreach (var field in fields.Where(f => typeof(IQueryable).IsAssignableFrom(f.FieldType))) to foreach (var field in fields.Where(f => typeof(ObjectQuery).IsAssignableFrom(f.FieldType))) This does result in the program above running successfully. However if you add something to enumerate the results of the query e.g. int i = 0; Console.WriteLine("Results"); foreach (var result in query) { Console.WriteLine("Result " + i++ + " = " + result); } and add some data to the 2 tables that have been created in the DB for you then you get a System.NotSupportedException thrown the first time the enumeration is enumerated: System.NotSupportedException with message Unable to create a constant value of type 'Test121011_Issue396_01.MyEntity'. Only primitive types or enumeration types are supported in this context. and StackTrace at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.ConstantTranslator.TypedTranslate(ExpressionConverter parent, ConstantExpression linq) at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TypedTranslator`1.Translate(ExpressionConverter parent, Expression linq) at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq) at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.NewArrayInitTranslator.&amp;lt;&amp;gt;c__DisplayClass89.&amp;lt;TypedTranslate&amp;gt;b__87(Expression e) at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext() at System.Data.Entity.Core.Common.CommandTrees.ExpressionBuilder.Internal.EnumerableValidator`3.Validate(IEnumerable`1 argument, String argumentName, Int32 expectedElementCount, Boolean allowEmpty, Func`3 map, Func`2 collect, Func`3 deriveName) at System.Data.Entity.Core.Common.CommandTrees.ExpressionBuilder.Internal.EnumerableValidator`3.Validate() at System.Data.Entity.Core.Common.CommandTrees.ExpressionBuilder.Internal.ArgumentValidation.CreateExpressionList(IEnumerable`1 arguments, String argumentName, Boolean allowEmpty, Action`2 validationCallback) at System.Data.Entity.Core.Common.CommandTrees.ExpressionBuilder.Internal.ArgumentValidation.CreateExpressionList(IEnumerable`1 arguments, String argumentName, Action`2 validationCallback) at System.Data.Entity.Core.Common.CommandTrees.ExpressionBuilder.Internal.ArgumentValidation.ValidateNewCollection(IEnumerable`1 elements, DbExpressionList&amp;amp; validElements) at System.Data.Entity.Core.Common.CommandTrees.ExpressionBuilder.DbExpressionBuilder.CreateNewCollection(IEnumerable`1 elements) at System.Data.Entity.Core.Common.CommandTrees.ExpressionBuilder.DbExpressionBuilder.NewCollection(IEnumerable`1 elements) at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.NewArrayInitTranslator.TypedTranslate(ExpressionConverter parent, NewArrayExpression linq) at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TypedTranslator`1.Translate(ExpressionConverter parent, Expression linq) at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq) at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.ConstantTranslator.TypedTranslate(ExpressionConverter parent, ConstantExpression linq) at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TypedTranslator`1.Translate(ExpressionConverter parent, Expression linq) at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq) at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TranslateLambda(LambdaExpression lambda, DbExpression input) at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TranslateLambda(LambdaExpression lambda, DbExpression input, DbExpressionBinding&amp;amp; binding) at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.OneLambdaTranslator.Translate(ExpressionConverter parent, MethodCallExpression call, DbExpression&amp;amp; source, DbExpressionBinding&amp;amp; sourceBinding, DbExpression&amp;amp; lambda) at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.OneLambdaTranslator.Translate(ExpressionConverter parent, MethodCallExpression call) at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.SelectManyTranslator.Translate(ExpressionConverter parent, MethodCallExpression call) at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.SequenceMethodTranslator.Translate(ExpressionConverter parent, MethodCallExpression call, SequenceMethod sequenceMethod) at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.TypedTranslate(ExpressionConverter parent, MethodCallExpression linq) at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TypedTranslator`1.Translate(ExpressionConverter parent, Expression linq) at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq) at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.Convert() at System.Data.Entity.Core.Objects.ELinq.ELinqQueryState.GetExecutionPlan(Nullable`1 forMergeOption) at System.Data.Entity.Core.Objects.ObjectQuery`1.GetResults(Nullable`1 forMergeOption) at System.Data.Entity.Core.Objects.ObjectQuery`1.&amp;lt;System.Collections.Generic.IEnumerable&amp;lt;T&amp;gt;.GetEnumerator&amp;gt;b__0() at System.Lazy`1.CreateValue() at System.Lazy`1.LazyInitValue() at System.Lazy`1.get_Value() at System.Data.Entity.Internal.LazyEnumerator`1.MoveNext() at Test121011_Issue396_01.Program.Main(String[] args) in c:\work\test\Test121011_Issue396_01\Test121011_Issue396_01\Program.cs:line 41

Viewing all articles
Browse latest Browse all 10318

Trending Articles