-
Notifications
You must be signed in to change notification settings - Fork 3.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
InvalidCastException when trying to use FreeText with a local variable as the language argument #13315
Comments
In the original expression, the argument is a |
Workaround: fixup the expression to replace references to a local variable with the value of that variable. static class Extensions
{
public static IQueryable<TSource> ReplaceLocalWithItsValue<TSource, TValue>(this IQueryable<TSource> source, Expression<Func<TValue>> localExpression, TValue value)
{
if (localExpression.Body is MemberExpression memberExpr && memberExpr.Expression is ConstantExpression constant)
{
var visitor = new MemberReplacementVisitor<TValue>(constant.Value, memberExpr.Member, value);
var newExpression = visitor.Visit(source.Expression);
return source.Provider.CreateQuery<TSource>(newExpression);
}
throw new ArgumentException("Invalid local expression");
}
private class MemberReplacementVisitor<TValue> : ExpressionVisitor
{
private readonly object _instance;
private readonly MemberInfo _member;
private readonly TValue _replacementValue;
public MemberReplacementVisitor(object instance, MemberInfo member, TValue replacementValue)
{
_instance = instance;
_member = member;
_replacementValue = replacementValue;
}
protected override Expression VisitMember(MemberExpression node)
{
if (node.Expression is ConstantExpression constant && Equals(constant.Value, _instance) && Equals(node.Member, _member))
return Expression.Constant(_replacementValue, typeof(TValue));
return base.VisitMember(node);
}
}
} Usage: int lcid = CultureInfo.CurrentCulture.LCID;
var results = await _dbContext.Items
.Where(i => EF.Functions.FreeText(m.Text, searchTerm, lcid))
.ReplaceLocalWithItsValue(() => lcid, lcid)
.ToListAsync(); |
Triage: moving this to the backlog to look into a general way of allowing values like this to not be parameterized. @smitpatel to link related issue. |
We need to decorate FreeText method's argument as NotParameterizedAttribute to avoid having a parameter there. |
To support non-literal value for the argument Fixes dotnet#13315
@smitpatel I just sent a PR for this (#20308) |
@smitpatel @ajcvickers August 2022 - I'm getting this error, using this code, .net 3.0: My azure instances are in 3.1 - The workaround listed here wouldn't work for my scenario, as I'm converting a SQL stored procedure using this method. |
@shahzadq77 this issue was about the use of the FreeText function with a parameter, but the code above doesn't seem to use FreeText. Please open a new issue with a runnable code sample and the full exception details. |
When I try to use a local variable for the
language
argument of theFreeText
method, I get the following exception:Steps to reproduce
Using a literal instead of the
lcid
variable works fine.The problem seems to be on this line:
https://github.com/aspnet/EntityFrameworkCore/blob/7b11733e091e937ea6f616ecf56ebc6fcb11955f/src/EFCore.SqlServer/Query/ExpressionTranslators/Internal/SqlServerFreeTextMethodCallTranslator.cs#L66
The translator assumes the expression to be a
ConstantExpression
, which means it can only work with a hard-coded literal value.Further technical details
EF Core version: 2.1.1
Database Provider: Microsoft.EntityFrameworkCore.SqlServer (2.1.1)
Operating system: Windows 10 v1803
IDE: VS2017 v15.8.1
The text was updated successfully, but these errors were encountered: