问题
I have a simple extension method for strings:
public static class FrenchStringExtensions
{
public static string ReplaceAccents(this string str)
{
return str
.Replace("ç", "c")
.Replace("é", "e")
.Replace("ê", "e")
.Replace("è", "e")
.Replace("ë", "e")
.Replace("â", "a")
.Replace("à", "a")
.Replace("î", "i")
.Replace("ï", "i")
.Replace("ô", "o")
.Replace("û", "u")
.Replace("ù", "u")
.Replace("ü", "u");
}
}
When I try to call this method inside Where()
clause like this:
var supportTeamsQuery = this.MasterContext.IncidentSupportTeams
.AsNoTracking()
.IsActive();
if (!string.IsNullOrEmpty(pattern))
{
pattern = pattern.ToLower().ReplaceAccents().Trim();
supportTeamsQuery = supportTeamsQuery
.Where(st =>
st.Name.ToLower().ReplaceAccents().Contains(pattern)
);
}
I have an error: The LINQ expression could not be translated...
If I use Replace()
calls right inside Where()
it works fine. For example:
supportTeamsQuery = supportTeamsQuery
.Where(st =>
st.Name
.ToLower()
.Replace("ç", "c")
.Replace("é", "e")
.Replace("ê", "e")
...
.Contains(pattern)
);
But I have several places in my code where I need to transform string this way so I want to move it to a separate method.
Is it possible to make it works?
回答1:
Difference here that when you inline methods in Where
clause, compiler generates Expression Tree with several Replace calls. When you call ReplaceAccents
, compiler generates only this call and EF can not access to body of that method. So you need a way to expand Expression Tree.
There are many solutions to do that. But try this extension, which is designed for that. https://github.com/axelheer/nein-linq/
According to the documentation, you have to do the following code changes:
public static class FrenchStringExtensions
{
[InjectLambda]
public static string ReplaceAccents(this string str)
{
_replaceAccentsFunc ??= ReplaceAccents().Compile();
return _replaceAccentsFunc(str);
}
Func<string, string> _replaceAccentsFunc;
private static Expression<Func<string, string>> ReplaceAccents()
{
return str =>
.Replace("ç", "c")
.Replace("é", "e")
.Replace("ê", "e")
.Replace("è", "e")
.Replace("ë", "e")
.Replace("â", "a")
.Replace("à", "a")
.Replace("î", "i")
.Replace("ï", "i")
.Replace("ô", "o")
.Replace("û", "u")
.Replace("ù", "u")
.Replace("ü", "u");
}
}
Then you can use your function after ToInjectable()
call
var supportTeamsQuery = this.MasterContext.IncidentSupportTeams
.ToInjectable()
.AsNoTracking()
.IsActive();
if (!string.IsNullOrEmpty(pattern))
{
pattern = pattern.ToLower().ReplaceAccents().Trim();
supportTeamsQuery = supportTeamsQuery
.Where(st =>
st.Name.ToLower().ReplaceAccents().Contains(pattern)
);
}
来源:https://stackoverflow.com/questions/64983665/ef-core-3-using-an-extension-method-of-string-inside-where-clause