C# EF Core 3-在Where子句中使用字符串的扩展方法

C# EF Core 3-在Where子句中使用字符串的扩展方法,c#,entity-framework-core,C#,Entity Framework Core,我有一个简单的字符串扩展方法: public static class FrenchStringExtensions { public static string ReplaceAccents(this string str) { return str .Replace("ç", "c") .Replace("é", "e") .Repl

我有一个简单的字符串扩展方法:

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");
    }
  }
当我尝试在
Where()
子句中调用此方法时,如下所示:

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)
          );
      }
我有一个错误:LINQ表达式无法翻译

如果我使用
Replace()。例如:

supportTeamsQuery = supportTeamsQuery
          .Where(st =>
            st.Name
            .ToLower()
            .Replace("ç", "c")
            .Replace("é", "e")
            .Replace("ê", "e")
            ...
            .Contains(pattern)
          );
但我的代码中有几个地方需要以这种方式转换字符串,所以我想将其移动到一个单独的方法


有可能使它工作吗?

这里的区别是,当您在
Where
子句中内联方法时,编译器会用几个替换调用生成表达式树。当您调用
replaceAncents
时,编译器只生成此调用,EF无法访问该方法的主体。所以需要一种方法来扩展表达式树

有很多解决方案可以做到这一点。但是试试这个扩展,它就是为此而设计的。

根据文档,您必须执行以下代码更改:

公共静态类FrenchString扩展
{
[Lambda]
公共静态字符串替换重音符号(此字符串str)
{
_replaceAncensFunc???=replaceAncents().Compile();
返回(str);;
}
函数(f);
私有静态表达式replaceAncents()
{
返回str=>
.替换(“ç”、“c”)
.替换(“e”、“e”)
.替换(“ê”、“e”)
.替换(“è”、“e”)
.替换(“ë”、“e”)
.替换(“a”、“a”)
.替换(“a”、“a”)
.替换(“î”、“i”)
.替换(“i”、“i”)
.替换(“ô”、“o”)
.替换(“ā”、“u”)
.替换(“ù”、“u”)
.替换(“u”、“u”);
}
}
然后,您可以在调用
ToInjectable()之后使用函数

var-supportTeamsQuery=this.MasterContext.IncidentSupportTeams
.ToInjectable()
.AsNoTracking()
.IsActive();
如果(!string.IsNullOrEmpty(模式))
{
pattern=pattern.ToLower().replaceAncents().Trim();
supportTeamsQuery=supportTeamsQuery
.其中(st=>
st.Name.ToLower().ReplaceAncents().Contains(模式)
);
}

IMO,与其以这种方式查询数据(查询将无效),不如存储规范化名称。也就是说,在将名称存储到数据库中之前,应该调用replaceAncents。只需存储“带重音的名称”和“标准化名称”。第一个用于向用户显示数据,第二个用于搜索。发生此错误的原因是您的LINQ将被转换为SqlServer查询,但无法转换(SqlServer中没有内置版本的
replaceAncent
)。如果您的数据在内存中,那么您的函数就可以正常工作。我认为您也可以这样做,将
模式
字符串更改为重音类型。这样您的查询就可以工作了。您试图做的似乎是重新发明排序规则重音敏感度。只需将数据库的排序规则更改为不区分重音(AI),或者如果您只需要在某个查询上使用EF Core 5,那么您也可以通过使用不区分大小写(CI)排序而不是区分大小写(CS)来摆脱ToLower。谢谢!这正是我要找的!