diff --git a/src/EFCore.Design/Query/Internal/LinqToCSharpSyntaxTranslator.cs b/src/EFCore.Design/Query/Internal/LinqToCSharpSyntaxTranslator.cs index ce59c297756..5f7a672da26 100644 --- a/src/EFCore.Design/Query/Internal/LinqToCSharpSyntaxTranslator.cs +++ b/src/EFCore.Design/Query/Internal/LinqToCSharpSyntaxTranslator.cs @@ -2039,6 +2039,28 @@ LiteralExpressionSyntax literal when literal.IsKind(SyntaxKind.NullLiteralExpres }; } + private Expression LiftTryExpression(TryExpression tryExpression) + { + using var _ = ChangeContext(ExpressionContext.Statement); + var name = UniquifyVariableName("temp"); + var variable = Expression.Parameter(tryExpression.Type, name); + var newBody = Expression.Assign(variable, tryExpression.Body); + var newTry = tryExpression.Update(newBody, tryExpression.Handlers, tryExpression.Finally, tryExpression.Fault); + + _liftedState.Statements.Add(GenerateVarDeclaration(name, DefaultExpression(Generate(variable.Type)))); + + var re = Translate(newTry); + _liftedState.Statements.Add(re); + _liftedState.VariableNames.Add(name); + _liftedState.Variables[variable] = name; + + var currentStack = _stack.Peek(); + currentStack.Variables[variable] = name; + currentStack.VariableNames.Add(name); + + return variable; + } + /// protected override Expression VisitNewArray(NewArrayExpression newArray) { @@ -2414,8 +2436,9 @@ protected override Expression VisitTry(TryExpression tryNode) case ExpressionContext.Expression: case ExpressionContext.ExpressionLambda: - throw new NotImplementedException(); - + var liftedVariable = LiftTryExpression(tryNode); + Result = Translate(liftedVariable); + return tryNode; default: throw new ArgumentOutOfRangeException(); } diff --git a/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.ClientMethods.cs b/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.ClientMethods.cs index a95f045c940..d7a8c742cdd 100644 --- a/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.ClientMethods.cs +++ b/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.ClientMethods.cs @@ -126,16 +126,17 @@ public static TValue ThrowReadValueException( throw new InvalidOperationException(message, exception); } + /// + /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to + /// the same compatibility standards as public APIs. It may be changed or removed without notice in + /// any release. You should only use it directly in your code with extreme caution and knowing that + /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static TValue ThrowExtractJsonPropertyException(Exception exception, IProperty property) - { - var entityType = property.DeclaringType.DisplayName(); - var propertyName = property.Name; - - throw new InvalidOperationException( + [EntityFrameworkInternal] + public static TValue ThrowExtractJsonPropertyException(Exception exception, string entityType, string propertyName) => throw new InvalidOperationException( RelationalStrings.JsonErrorExtractingJsonProperty(entityType, propertyName), exception); - } /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to diff --git a/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.cs b/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.cs index 8b5ff6bd2e2..3e89590204c 100644 --- a/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.cs @@ -2863,20 +2863,33 @@ Expression valueExpression && !buffering) { var exceptionParameter = Parameter(typeof(Exception), name: "e"); - - var catchBlock = Catch( - exceptionParameter, - Call( - ThrowReadValueExceptionMethod.MakeGenericMethod(valueExpression.Type), + CatchBlock? catchBlock = null; + if (property != null) + { + catchBlock = Catch( exceptionParameter, - Call(dbDataReader, GetFieldValueMethod.MakeGenericMethod(typeof(object)), indexExpression), - Constant(valueExpression.Type.MakeNullable(nullable), typeof(Type)), - _parentVisitor.Dependencies.LiftableConstantFactory.CreateLiftableConstant( - property, - LiftableConstantExpressionHelpers.BuildMemberAccessLambdaForProperty(property), - property + "Property", - typeof(IPropertyBase)))); - + Call( + ThrowReadValueExceptionMethod.MakeGenericMethod(valueExpression.Type), + exceptionParameter, + Call(dbDataReader, GetFieldValueMethod.MakeGenericMethod(typeof(object)), indexExpression), + Constant(valueExpression.Type.MakeNullable(nullable)), + _parentVisitor.Dependencies.LiftableConstantFactory.CreateLiftableConstant( + property, + LiftableConstantExpressionHelpers.BuildMemberAccessLambdaForProperty(property), + property.Name + "Property", + typeof(IPropertyBase)))); + } + else + { + catchBlock = Catch( + exceptionParameter, + Call( + ThrowReadValueExceptionMethod.MakeGenericMethod(valueExpression.Type), + exceptionParameter, + Call(dbDataReader, GetFieldValueMethod.MakeGenericMethod(typeof(object)), indexExpression), + Constant(valueExpression.Type.MakeNullable(nullable)), + Constant(null,typeof(IPropertyBase)))); + } valueExpression = TryCatch(valueExpression, catchBlock); } @@ -3005,7 +3018,8 @@ private Expression CreateReadJsonPropertyValueExpression( Call( ThrowExtractJsonPropertyExceptionMethod.MakeGenericMethod(resultExpression.Type), exceptionParameter, - Constant(property, typeof(IProperty)))); + Constant(property.DeclaringType.DisplayName(), typeof(string)), + Constant(property.Name, typeof(string)))); resultExpression = TryCatch(resultExpression, catchBlock); } diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/PrecompiledQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/PrecompiledQuerySqlServerTest.cs index b209e80f11e..0cb3ade0a10 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/PrecompiledQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/PrecompiledQuerySqlServerTest.cs @@ -2091,7 +2091,7 @@ public override DbContextOptionsBuilder AddOptions(DbContextOptionsBuilder build // TODO: Figure out if there's a nice way to continue using the retrying strategy var sqlServerOptionsBuilder = new SqlServerDbContextOptionsBuilder(builder); sqlServerOptionsBuilder.ExecutionStrategy(d => new NonRetryingExecutionStrategy(d)); - return builder; + return builder.EnableDetailedErrors(); } public override PrecompiledQueryTestHelpers PrecompiledQueryTestHelpers