Linq SqlMethods.Like失败了

时间:2010-04-06 12:02:21

标签: .net linq-to-entities

我正在关注提示here,尝试利用在枚举器被触发之前不会创建sql的语句。但是,我在下面的代码中收到以下错误。我正在使用Linq2Entities,而不是linq2sql。有没有办法在Linq2entities中执行此操作?

方法'Boolean Like(System.String,System.String)'不能在客户端上使用;它仅用于转换为SQL。

            query = db.MyTables.Where(x => astringvar.Contains(x.Field1));

            if (!String.IsNullOrEmpty(typeFilter))
            {
                if (typeFilter.Contains('*'))
                {
                    typeFilter = typeFilter.Replace('*', '%');
                    query = query.Where(x=> SqlMethods.Like(x.Type, typeFilter));
                }
                else
                {
                    query  = query.Where(x => x.Type == typeFilter);
                }
            }

注意:db是映射到sql server的实体。

5 个答案:

答案 0 :(得分:11)

我不知道如何让Entity Framework使用“真正的”LIKE运算符,但可能的解决方法是用StartsWithContains和{{来表达LIKE表达式1}}

例如:

EndsWith

等等......

请注意,它与在SQL中使用LIKE并不完全等效:例如LIKE 'a%' => StartsWith("a") LIKE '%a' => EndsWith("a") LIKE '%a%' => Contains("a") LIKE 'a%b' => StartsWith("a") && EndsWith("b") LIKE 'a%b%' => StartsWith("a") && Contains("b") 会导致LIKE '%abc%bcd%'。这将匹配“abcd”,即使原始的LIKE条件不会。但对于大多数情况来说,它应该足够好了。

这是一个示例实现,使用PredicateBuilderLinqKit基于LIKE模式构建表达式:

Contains("abc") && Contains("bcd")

以下是你如何使用它:

public static class ExpressionHelper
{
    public static Expression<Func<T, bool>> StringLike<T>(Expression<Func<T, string>> selector, string pattern)
    {
        var predicate = PredicateBuilder.True<T>();
        var parts = pattern.Split('%');
        if (parts.Length == 1) // not '%' sign
        {
            predicate = predicate.And(s => selector.Compile()(s) == pattern);
        }
        else
        {
            for (int i = 0; i < parts.Length; i++)
            {
                string p = parts[i];
                if (p.Length > 0)
                {
                    if (i == 0)
                    {
                        predicate = predicate.And(s => selector.Compile()(s).StartsWith(p));
                    }
                    else if (i == parts.Length - 1)
                    {
                        predicate = predicate.And(s => selector.Compile()(s).EndsWith(p));
                    }
                    else
                    {
                        predicate = predicate.And(s => selector.Compile()(s).Contains(p));
                    }
                }
            }
        }
        return predicate;
    }
}

我只是用一个简单的EF模型尝试过它,它似乎运行良好:)

答案 1 :(得分:4)

您可以执行ESQL并执行以下操作..

     db.MyTables.Where("it.Type like '" + typeFilter + "'").ToList();

答案 2 :(得分:4)

SqlMethods class旨在与LINQ-to-SQL一起使用。当您使用它的方法时(公共文档告诉您不要这样做,它不适合公共使用),LINQ-to-Entities的IQueryable提供程序不知道如何处理它或如何翻译它

如果在过滤器的开头或结尾有一个通配符,那么您可以在String类上使用StartsWithEndsWith方法,并且LINQ-to-Entities将支持。

但是,在这种情况下,您拥有可变数量的通配符,因此您必须下拉到ESQL级别并从中构建查询,如Nix's answer所示。

答案 3 :(得分:0)

您可以使用链接到实体

中的真实内容

添加

    <Function Name="String_Like" ReturnType="Edm.Boolean">
      <Parameter Name="searchingIn" Type="Edm.String" />
      <Parameter Name="lookingFor" Type="Edm.String" />
      <DefiningExpression>
        searchingIn LIKE lookingFor
      </DefiningExpression>
    </Function>

到此标签中的EDMX:

  

EDMX:EDMX / EDMX:运行/ EDMX:ConceptualModels /模式

还要记住<schema namespace="" />属性

中的命名空间

然后在上面的命名空间中添加一个扩展类:

public static class Extensions
{
    [EdmFunction("DocTrails3.Net.Database.Models", "String_Like")]
    public static Boolean Like(this String searchingIn, String lookingFor)
    {
        throw new Exception("Not implemented");
    }
}

此扩展方法现在将映射到EDMX功能。

此处有更多信息:http://jendaperl.blogspot.be/2011/02/like-in-linq-to-entities.html

答案 4 :(得分:0)

我发布了my solution here,以防万一,在这里:

2019更新

对于Entity Framework 6.2,您可以使用DBFunctions

例如:

try
{
    using (var db = new YOUREntities())
    {
        var data = db.LenderProgram.Where(i => DbFunctions.Like(i.LenderProgramCode, "OTO%"))
            .ToList();
        return data;
    }
}
catch (Exception e)
{
    e.HandleException();
}