我有一个与此类似的模型:
Public class Item {
public int Id { get; set; }
public string Name { get; set; }
public DateTime? StartTime { get; set; }
public DateTime? EndTime { get; set; }
public int? TotalTime
{
get
{
return Convert.ToInt32(EndTime.Value - StartTime.Value).TotalMinutes);
}
}
etc...
然后我得到一个项目列表:
IQueryable<Items> items = itemsContext.Items.Where(e => e.Id > 0);
我做了一些计算,运行一些其他代码,然后最后我想返回按 Name ASC 和 TotalTime DESC 排序的项目列表。这是我尝试过的:
items = items.OrderBy(e => e.Name).ThenByDescending(e => e.TotalTime);
但我收到错误:“无法翻译 LINQ 表达式。要么以可翻译的形式重写查询,要么通过插入对 AsEnumerable()、AsAsyncEnumerable 的调用显式切换到客户端计算()、ToList() 或 ToListAsync()。”
我也尝试过这个,但得到同样的错误:
items = items.OrderBy(e => e.Name).ThenByDescending(e => e.TotalTime ?? 0);
如何按 TotalTime 对数据集进行排序?
最佳答案
- 由于
TotalTime
不是您数据库的一部分,因此您需要使用[NotMapped]
对其进行注释。 - 然后您需要首先加载项目,然后按它们排序。
- 但是,如果您想在数据库服务器中执行分页或排序,则需要直接在查询中使用
EndTime
和StartTime
。
方法 1:先加载,然后在应用程序代码中排序:
List<Items> loadedItems = await itemsContext.Items
.Where( e => e.Id > 123 )
.ToListAsync()
.ConfigureAwait(false); // `ConfigureAwait(false)` MAY be optional, depending on your application.
List<Items> sortedItems = loadedItems
.OrderBy(e => e.Name)
.ThenByDescending(e => e.TotalTime)
.ToList(); // <-- Note this is NOT `ToListAsync` because the items are already loaded into memory.
方法 2:在 SQL 中排序:
List<Items> loadedSortedItems = await itemsContext.Items
.Where( e => e.Id > 123 )
.OrderBy( e => e.Name )
.ThenByDescending( e => e.EndTime - e.StartTime )
.ToListAsync()
.ConfigureAwait(false);
对您的类(class)进行更改
我会将您的类(class)修改为如下所示:
public class Item {
public int Id { get; set; }
public string Name { get; set; }
public DateTime? StartTime { get; set; }
public DateTime? EndTime { get; set; }
[NotMapped]
public int? TotalTimeMinutes
{
get
{
if( this.EndTime == null || this.StartTime == null ) return null;
TimeSpan diff = this.EndTime.Value - this.StartTime.Value;
return (Int32)Math.Round( diff.TotalMinutes );
}
}
NotMapped
属性向 Entity Framework 明确表明它应该忽略该属性。- 请注意该属性如何包含单位名称(“分钟”),否则属性是否为毫秒、秒、分钟等并不明显。
- 另请注意该属性如何检查
StartTime
和EndTime
是否为 null,并在这种情况下返回null
。您的代码没有,这意味着如果数据库中存在NULL
值或任何Item
对象实例未完全初始化,您的程序将会崩溃。 - 如果
StartTime
和EndTime
值不能为NULL
,那么您需要添加NOT NULL
添加到数据库并更新 EF 实体类,以便属性为DateTime
而不是DateTime?
。
关于c# - Entity Framework Core - 对计算字段进行排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64435255/