Skip to content

Adding a new EF.Functions function with no object references #12527

@MikeDempseyFL

Description

@MikeDempseyFL

I am trying to write additional EF.Functions that must be executed on the server.

This works well if at least one of the function arguments is a reference to a database column. (via the entity model)

If all arguments are constants, or if there are no arguments, it results in an exception.
This exception occurs without our custom IMethodCallTranslator code getting called.
Linq (?) apparently decides that if there are no object references then it can process the expression locally ... which of course it can not.
The second exception message, below, is from the exception we throw when you try to evaluate one of our extension functions locally.
The stack trace seems to indicate that the problem occurs when initially building the Linq expression tree - before the 'Relational' layer gets a chance to look at it.

Exception:
System.InvalidOperationException : An exception was thrown while attempting to evaluate a LINQ query parameter expression.
----> System.InvalidOperationException : Teradata Database specific functions can not be evaluated on the client.

Stack trace:
at Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.Internal.ParameterExtractingExpressionVisitor.Evaluate(Expression expression, String& parameterName)
at Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.Internal.ParameterExtractingExpressionVisitor.TryExtractParameter(Expression expression)
at Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.Internal.ParameterExtractingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
at System.Linq.Expressions.ExpressionVisitor.Visit(ReadOnlyCollection1 nodes) at Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.Internal.ParameterExtractingExpressionVisitor.VisitNew(NewExpression node) at System.Linq.Expressions.NewExpression.Accept(ExpressionVisitor visitor) at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node) at System.Linq.Expressions.ExpressionVisitor.VisitLambda[T](Expression1 node)
at Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.Internal.ParameterExtractingExpressionVisitor.VisitLambda[T](Expression1 node) at System.Linq.Expressions.Expression1.Accept(ExpressionVisitor visitor)
at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
at System.Linq.Expressions.ExpressionVisitor.VisitUnary(UnaryExpression node)
at Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.Internal.ParameterExtractingExpressionVisitor.VisitUnary(UnaryExpression unaryExpression)
at System.Linq.Expressions.UnaryExpression.Accept(ExpressionVisitor visitor)
at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
at System.Dynamic.Utils.ExpressionVisitorUtils.VisitArguments(ExpressionVisitor visitor, IArgumentProvider nodes)
at System.Linq.Expressions.ExpressionVisitor.VisitMethodCall(MethodCallExpression node)
at Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.Internal.ParameterExtractingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
at Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.Internal.ParameterExtractingExpressionVisitor.ExtractParameters(Expression expression)
at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.Execute[TResult](Expression query)
at Remotion.Linq.QueryableBase1.GetEnumerator() at System.Collections.Generic.List1.AddEnumerable(IEnumerable1 enumerable) at System.Linq.Enumerable.ToList[TSource](IEnumerable1 source)
at Teradata.EntityFrameworkCore.Tests.TeradataQueryTeradataFunctionTests.NumericTests() in C:\AppSourceCurrent\TdNetDp\Tests\EntityFramework\EFCore.Teradata.Tests\TeradataQueryTeradataFunctionTests.cs:line 142
--InvalidOperationException
at Teradata.EntityFrameworkCore.TeradataDbFunctionsExtensions.Random(DbFunctions _, Int32 lowerBound, Int32 upperBound) in C:\AppSourceCurrent\TdNetDp\src\TdDotNetDataProvider\EFCore.Teradata\Extensions\TeradataDbFunctionsExtensions.cs:line 46
at lambda_method(Closure )
at Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.Internal.ParameterExtractingExpressionVisitor.Evaluate(Expression expression, String& parameterName)

Steps to reproduce

Can not be reproduced without an Entity Provider that implements EF.Functions of this type.
Example 1
The function RANDOM(1, 256) should generate a random number between 1 and 256 for each row in the result set. (This random number will generally be used in an expression, but may sometimes need to be returned in the result set.)
Example 2
The function CurrentUser() should return the user name of the user that connected the database session.

Further technical details

EF Core version: 2.1
Database Provider: Teradata.EntityFrameworkCore
Operating system: Windows 10
IDE: Visual Studio 2017 15.7.2

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions