c# - Entity Framework 中有序集的并集,然后跳过

标签 c# sql entity-framework linq

我有一个类(class)表,我想对其多个字段执行文本搜索。但是,搜索应该按顺序进行:例如类(class)有一个 Keywords 字段和 Description 字段。搜索应优先于通过关键字找到的值。所有内容都应该按日期排序,但只有在考虑优先级之后才可以。

我最后还使用了 https://github.com/troygoode/PagedList 中的 ToPagedList() (我认为它只是使用 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() 之外,这段代码几乎满足了我的要求。这里的每个联合都可以检索相同的记录,因此我可能会多次收到它,并且由于虚拟 Order 字段,Distinct() 不会强制唯一性。我无法将 Distinct 放在 Select(x => x.Record) 之后,因为 ToPagedList(..) 需要对集合进行排序(结果:仅 LINQ to Entities 中的排序输入支持“Skip”方法。 异常(exception))

有什么想法吗?

到目前为止,我有一个:在 Distinct 之后添加 Order 字段,但这意味着我必须将这些 Contains 检查写入两次,我认为这非常丑陋解决方案。

最佳答案

首先,由于您由于 Order 值不同而投影唯一记录,因此请将 Union 运算符替换为 Concat(这是 LINQ相当于 SQL UNION ALL)。

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 作为键,并为每个值取最小 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);

关于c# - Entity Framework 中有序集的并集,然后跳过,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40257355/

相关文章:

c# - 如何 - 跨 tcp/ip 边界验证调用程序集

c# - Windows 窗体应用程序 (c#) : using an input from form y in form x (threading problem)

c# - 使用 ASP .NET Core Identity 和 EntityFrameworkCore 注册新用户时出现 InvalidOperationException

c# - 使用聚合和分组依据的 LINQ 查询

c# - 迁移ASP.NET MVC3的数据库文件

c# - 什么是最好的计算平台 SQL 或 c#

c# - 确定一副牌洗牌的程度

mysql - 我的查询有什么问题

java - JOOQ 与 hibernate 行为

mysql - 复杂的查询需要太多时间传输