在实体框架中联合有序集然后跳过

时间:2016-10-26 08:32:02

标签: c# sql entity-framework linq

我有一个课程表,我想对其中的几个字段执行文本搜索。但是,应该订购搜索:例如,课程有Description字段和Keywords字段。搜索应优先于ToPagedList()找到的值。一切都应该按日期排序,但只有在考虑优先级之后。

我也在plot的最后使用Skip()(我认为它只使用Top()string[] word = /*Search words*/ var data = db.LessonsLearneds.Where(dbRecord => words.Any(word => dbRecord.SearchKeywords.StartsWith(word + ",") || dbRecord.SearchKeywords.Contains("," + word + ",") || dbRecord.SearchKeywords.EndsWith("," + word))) .Select(x => new { Record = x, Order = 1 }); data = data.Union( db.LessonsLearneds .Where(dbRecord => words.Any(word => dbRecord.Title.Contains(word))) .Select(x => new { Record = x, Order = 2 })); data = data.Union( db.LessonsLearneds .Where(dbRecord => words.Any(word => dbRecord.Description.Contains(word))) .Select(x => new { Record = x, Order = 3})); data = data.Union( db.LessonsLearneds .Where(dbRecord => words.Any(word => dbRecord.Lesson.Contains(word))) .Select(x => new { Record = x, Order = 4 })); return data .Distinct() .OrderBy(x => x.Order) .ThenByDescending(x => x.Record.Date) .Select(x => x.Record) .ToPagedList(pageNumber, pageSize); 来管理网页)

这是我到目前为止所做的:

Distinct()

总的来说,除了Distinct()之外,这段代码几乎可以实现我想要的功能。这里的每个联合都可以检索相同的记录,因此我可能会多次收到它,而Order不会因虚拟Distinct字段而强制唯一性。我无法将Select(x => x.Record)放在ToPagedList(..)之后因为The method 'Skip' is only supported for sorted input in LINQ to Entities.需要对该集进行排序(导致:Order异常)

有什么想法吗?

到目前为止我有一个:在Distinct之后添加{{1}}字段,但这意味着我必须编写两次包含检查,我认为这是非常难看的解决方案。

2 个答案:

答案 0 :(得分:1)

您可以将Distinct替换为GroupBySelect,如下所示:

return data
        .GroupBy(x => x.Record)
        .Select(g => g.OrderBy(x => x.Order).ThenByDescending(x => x.Record.Date).First())
        .OrderBy(x => x.Order)
        .ThenByDescending(x => x.Record.Date)
        .Select(x => x.Record)
        .ToPagedList(pageNumber, pageSize);

这种方法的不幸副作用是你需要在第一个OrderBy内重复Select,但它应该产生你正在寻找的结果。

答案 1 :(得分:1)

首先,由于由于Order值不同而要投射唯一记录,因此将Union运算符替换为Concat(这是SQL UNION ALL的LINQ等价物)。

string[] word = /*Search words*/
var data = db.LessonsLearneds.Where(dbRecord => words.Any(word =>
        dbRecord.SearchKeywords.StartsWith(word + ",") ||
        dbRecord.SearchKeywords.Contains("," + word + ",") ||
        dbRecord.SearchKeywords.EndsWith("," + word)))
        .Select(x => new { Record = x, Order = 1 });

data = data.Concat(
    db.LessonsLearneds
        .Where(dbRecord => words.Any(word => dbRecord.Title.Contains(word)))
        .Select(x => new { Record = x, Order = 2 }));

data = data.Concat(
     db.LessonsLearneds
        .Where(dbRecord => words.Any(word => dbRecord.Description.Contains(word)))
        .Select(x => new { Record = x, Order = 3}));

data = data.Concat(
     db.LessonsLearneds
        .Where(dbRecord => words.Any(word => dbRecord.Lesson.Contains(word)))
        .Select(x => new { Record = x, Order = 4 }));

然后将Distinct替换为GroupBy,使用x.Record作为密钥,并为每个分组取{min} Order,其余部分与当前查询一样:

return data
     .GroupBy(x => x.Record)
     .Select(g => new { Record = g.Key, Order = g.Min(x => x.Order) })
     .OrderBy(x => x.Order)
     .ThenByDescending(x => x.Record.Date)
     .Select(x => x.Record)
     .ToPagedList(pageNumber, pageSize);