如何使LINQ执行(SQL)LIKE范围搜索

时间:2017-10-26 11:11:12

标签: c# sql asp.net linq linq-to-sql

我非常需要帮助,我一直试图这样做。

所以我有这个查询:

Select name from BlaBlaBla

order by 

case when name like '9%' then 1 end,
case when name like '8%' then 1 end,
case when name like '7%' then 1 end,
case when name like '6%' then 1 end,
case when name like '5%' then 1 end,
case when name like '4%' then 1 end,
case when name like '3%' then 1 end,
case when name like '2%' then 1 end,
case when name like '1%' then 1 end,
case when name like '0%' then 1 end,

name

我想在一个新的C#,Asp.Net,类,在我的解决方案中,到域项目中实现它,所以它将是一个OrderType过滤器,用于某些功能......

现在我有这个:

var param = Expression.Parameter(typeof(T), "item");

var paramName = Expression.Property(param, "Name");
var regexMatch = Expression.Constant("^[0-9]");
var startsWithDigit = Expression.Call(typeof(Regex), "IsMatch", 
                                             null, paramName);

var lambda = Expression.Lambda<Func<T, bool>>(startsWithDigit, 
                                              param);

return namesList.OrderBy(lambda)
           .ThenBy(BlaBla1())
           .ThenByDescending(BlaBla2())
           .ThenByDescending(BlaBla3())
           .ThenBy(BlaBla4());

但它告诉我,Expression不包含&#34; IsMatch&#34;方法

你能帮帮我吗? 谢谢!!!

3 个答案:

答案 0 :(得分:1)

这里的问题是包含Regex的表达式无法转换为SQL,所以即使您成功构建了正确的表达式,也无法在LINQ中使用它到SQL后端。但是,SQL的LIKE方法也支持范围通配符,如[0-9],所以诀窍是让你的LINQ转换为包含LIKE语句的SQL。

LINQ-to-SQL提供了明确使用SQL LIKE语句的可能性

return namesList.OrderBy(r => SqlMethods.Like(r.Name, "[0-9]%")) ...

SqlMethods类只能在LINQ-to-SQL中使用。在Entity Framework中,有一些字符串函数可以隐式转换为LIKE ,但它们都不启用范围通配符([x-y])。在EF这样的声明......

return namesList.OrderBy(r => r.Name.StartsWith("[0-9]")) ...

......会转化为废话:

[Name] LIKE '~[0-9]%' ESCAPE '~'

即。它徒劳地寻找以文字字符串&#34; [0-9]&#34;开头的名字。所以只要你继续使用LINQ-to-SQL SqlMethods.Like就可以了。

在Entity Framework 6.1.3(及更低版本)中,我们必须使用稍微不同的方法来获得相同的结果......

return namesList.OrderBy(r => SqlFunctions.PatIndex("[0-9]%", c.Name) == 1) ...

...因为SqlFunctions中的PatIndex也支持范围模式匹配。

但是在Entity Framwork 6.2中,由于新的DbFunctions.Like功能,我们重新回到了LINQ-to-SQL的轨道:

return namesList.OrderBy(r => DbFunctions.Like(r.Name, "[0-9]%")) ...

最后,Entity Framework核心还有一个Like函数:

return namesList.OrderBy(r => EF.Functions.Like(r.Name, "[0-9]%")) ...

答案 1 :(得分:0)

下面您将看到一种处理订单案例的方法示例。

jQuery(".job_col").hover(function() {

  var current = jQuery(this);
  current.find(".plus").addClass("hi");
}, function() {

});

答案 2 :(得分:0)

如果我是你,我不会尝试使用表达式来解决这个问题,因为它带来了很多复杂性。

我看到你想要一个通用的方法,所以它可以使用不同的域实体,但你期望每个实体都有Name属性。 您可以通过定义包含Name属性的接口以更简单的方式解决此问题。像这样:

    public static void Main()
    {
        var test = new List<YourDomainEntity>()
        {
            new YourDomainEntity() { Name = "1test", OtherProperty = "1"},
            new YourDomainEntity() { Name = "2test",  OtherProperty = "2" },
            new YourDomainEntity() { Name = "2test", OtherProperty = "1"   }
        };

        var k = Foo(test).ToList();
    }

    public interface INameOrderable
    {
        string Name { get; set; }
    }

    public interface IOtherPropertyOrderable
    {
        string OtherProperty { get; set; }
    }

    public static IEnumerable<T> Foo<T>(IEnumerable<T> list) where T : INameOrderable, IOtherPropertyOrderable
    {
        return list.OrderBy(a => a.Name, new NamesDescComparer()).ThenBy(b => b.OtherProperty);
    }

    public class NamesDescComparer : IComparer<string>
    {
        public int Compare(string x, string y) => -String.CompareOrdinal(x, y);
    }

    class YourDomainEntity : INameOrderable, IOtherPropertyOrderable
    {
        public string OtherProperty { get; set; }
        public string Name { get; set; }
    }

我相信方法Foo正是您所寻找的。

请注意where T : INameOrderable部分。它将此方法的使用限制为实现INameOrderable接口

的实体