EF Core 3-在Where子句中使用字符串的扩展方法 [英] EF Core 3 - Using an extension method of string inside Where clause

查看:131
本文介绍了EF Core 3-在Where子句中使用字符串的扩展方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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");
    }
  }

当我尝试在 Where()子句中这样调用此方法时:

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)
          );
      }

我有一个错误: LINQ表达式无法翻译...

如果我在 Where()内直接使用 Replace()调用,则效果很好.例如:

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?

推荐答案

此处的区别在于,当您在 Where 子句中内联方法时,编译器会生成带有多个Replace调用的Expression Tree.当您调用 ReplaceAccents 时,编译器仅生成此调用,并且EF无法访问该方法的主体.因此,您需要一种扩展表达式树的方法.

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.

有很多解决方案可以做到这一点.但是,请尝试为此设计的扩展. https://github.com/axelheer/nein-linq/

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");
    }
}

然后您可以在 ToInjectable()调用之后使用函数

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)
          );
      }

这篇关于EF Core 3-在Where子句中使用字符串的扩展方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆