Linq to Entities - 多列搜索

时间:2015-01-16 15:26:52

标签: c# linq entity-framework

我有一个具有3个可搜索属性的实体Car

Brand       Model            Code
----------- ---------------- -----------
Ferrari     F40              X7844ADFS
Porsche     911 Turbo        YSAD42313

我有以下方法:

public IEnumerable<Car> SearchCar(string search)
{
    IEnumerable<Car> result = Enumerable.Empty<Car>().AsEnumerable();

    if (!string.IsNullOrEmpty(search))
    {
        var preResult = from A in _context.Cars
                  select new { TextField = A.Brand + " " +  A.Model + A.Code,
                               car = A};
        result = preResult.Where(x => x.TextField.ToLower().Contains(searchValue.ToLower())).Select(v => v.Car);
    }
    return result;
}

搜索示例:

  • 保时捷Turbo
  • 法拉利
  • YSAD42313

然而,这种方法对第一种方法(保时捷Turbo)不起作用。反正这样做是为了在所有情况下都有效吗?

2 个答案:

答案 0 :(得分:5)

您需要拆分search变量中的不同单词,然后单独搜索这些单词。像这样:

var splitSearch = search.Split(' ');
result = preResult.Where(x => splitSearch.All(s => x.TextField.ToLower().Contains(s)))
                  .Select(v => v.Car);

答案 1 :(得分:1)

IronMan84的另一个答案,我认为它会更有效率,因为在搜索之前它不会连接所有字段。使用TextField和汽车创建匿名类型是不必要的,因为您只返回汽车。 你确定上下文中的对象叫做Persons而不是Cars吗?

public IEnumerable<Car> SearchCar(string search)
{
    if (string.IsNullOrEmpty(search)) return Enumerable.Empty<Car>().AsEnumerable();
    var terms = search.ToLower().Split(' ');
    return _context.Cars
        .Where(x => terms.All(t => 
            x.Brand.ToLower().Contains(t) 
            || x.Model.ToLower().Contains(t)
            || x.Code.ToLower().Contains(t)));
}

另请注意,如果您使用不区分大小写的排序规则连接到数据库,则可以在所有情况下省略ToLower()。