如何对以日期开头的字符串添加额外排序规则?
实现方案
完全可以实现,我们可以通过判断值的前10位是否符合dd/MM/yyyy日期格式,将符合格式的内容按日期优先级排序,不符合格式的内容可以按原有逻辑/文本顺序排列,以下是两种适配不同场景的实现方案:
方案1:内存排序(兼容性最高,无EF翻译报错风险)
因为EF无法直接翻译C#原生的日期解析方法,最稳妥的方式是先把关联数据查询出来,再在内存中做自定义排序,修改后代码如下:
var result = await (from book in db.booksTable where book.IdCategory == request.bookCategory select new { Author = book.Author ?? "unknown", Opinions = (from opinion in db.opinionsTable join critic in db.criticTable on opinion.IdCritic equals critic.Id into c from critic in c.DefaultIfEmpty() where book.id == opinion.IdBook && critic.order != null select new { Value = opinion.Text ?? "empty", critic.Topic, critic.Order // 保留原有排序字段 }).ToList() // 内存中自定义排序逻辑 .OrderBy(x => x.Order) .ThenBy(x => { // 尝试截取前10位解析为dd/MM/yyyy格式日期 if (x.Value.Length >= 10 && DateTime.TryParseExact(x.Value.AsSpan(0,10), "dd/MM/yyyy", null, System.Globalization.DateTimeStyles.None, out var date)) { return date; } // 非日期开头的内容默认排在日期内容之后,要改排在前面把MaxValue改成MinValue即可 return DateTime.MaxValue; }) .ThenBy(x => x.Value) // 非日期内容按文本排序,不需要可删除 .ToList() } ).ToListAsync();
方案2:数据库端排序(性能更高,适合数据量大的场景)
如果你使用SQL Server等支持字符串转日期函数的数据库,可以用EF内置的函数映射直接在数据库层面完成排序,不需要拉取全量数据到内存,只需修改orderby段代码即可:
orderby critic.order, // 103是SQL Server中dd/MM/yyyy格式的日期样式码,其他数据库需调整对应转换参数 EF.Functions.IsDate(EF.Functions.Substring(opinion.Text, 1, 10)) == true ? EF.Functions.ConvertToDateTime(EF.Functions.Substring(opinion.Text, 1, 10), 103) : DateTime.MaxValue, opinion.Text
排序效果示例
你给出的样例Value经过上述升序排序后输出顺序为:
- "09/01/2000 other description"
- "05/01/2021 other description"
- "01/12/2021 other description"
- "example"
- "Sample description1"
- "Sample description2"
如果需要日期降序,内存排序时把return date改为return date.Ticks * -1,数据库排序时在对应字段后加desc关键字即可。
内容的提问来源于stack exchange,提问作者jrJerry
相关产品推荐
相关产品推荐

