【发布时间】:2019-07-26 15:52:04
【问题描述】:
我的 linq 查询有问题,我试图从中获取某些信息,但根本找不到问题所在。我的 ef 核心数据库中有工具、任务和一个 M-N ToolTask 实体。此查询包括 2 个左外连接和最后一个 group by。
即使我正在检查分组值是否不为空,我仍然会收到一条错误消息,例如“可空对象必须有一个值”。我在这里想念什么?
此外,这个 linq 查询似乎是在客户端评估的,我能做些什么来使其成为服务器端吗?当我由于某种原因在代码中没有“let maxDateV ...”行时,它一直是服务器端。
var max = (from t in _fabContext.Tools
join tt in _fabContext.ToolTask on t.ToolId equals tt.ToolId into tt1
from tt in tt1.DefaultIfEmpty()
join ts in _fabContext.Tasks on tt.TaskId equals ts.TaskId into ts1
from ts in ts1.DefaultIfEmpty()
group tt by tt.ToolId into g
let maxOrderV = g.Max(c => c != null ? c.Order : 0)
let maxDateV = g.Max(c => c != null ? c.Task.ExportDate : DateTime.MinValue)
select new
{
ToolId = g.Key,
MaxOrder = maxOrderV,
MaxExportDate = maxDateV
}).ToDictionary(d => d.ToolId, d =>
new OrderExportDate {
Order = d.MaxOrder,
ExportDate = d.MaxExportDate
});
更新 1(实体类):
任务
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
namespace Main.DataLayer.EfClasses
{
public class Task
{
public int TaskId { get; private set; }
[Required]
public string Name { get; private set; }
[Required]
public int ProfileId { get; private set; }
[Required]
public DateTime ExportDate { get; private set; }
private HashSet<ToolTask> _toolTask;
public IEnumerable<ToolTask> ToolTask => _toolTask?.ToList();
private Task()
{
}
public Task(
string name,
int profileId,
DateTime exportDate)
{
Name = name;
ProfileId = profileId;
ExportDate = exportDate;
}
}
}
工具任务
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
namespace Main.DataLayer.EfClasses
{
public class ToolTask
{
public int ToolId
{
get; private set;
}
public Tool Tool
{
get; private set;
}
public int TaskId
{
get; private set;
}
public Task Task
{
get; private set;
}
[Required]
public int SortOrder
{
get; private set;
}
private ToolTask() { }
internal ToolTask(Tool tool, Task task, int sortOrder)
{
Tool = tool;
ToolId = tool.ToolId;
Task = task;
TaskId = task.TaskId;
SortOrder = sortOrder;
}
public void ChangeOrder(int order)
{
SortOrder = order;
}
}
}
工具
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
using Main.DataLayer.EfCode;
namespace Main.DataLayer.EfClasses
{
public class Tool
{
public int ToolId
{
get; private set;
}
[Required]
public string Name
{
get; private set;
}
[Required]
public string Model
{
get; private set;
}
private HashSet<ToolTask> _toolTask;
public IEnumerable<ToolTask> ToolTask => _toolTask?.ToList();
internal Tool() { }
public Tool(string name, string model)
{
Name = name;
Model = model;
_toolTask = new HashSet<ToolTask>();
}
public void AddTask(Task task, int sortOrder)
{
_toolTask?.Add(new ToolTask(this, task, sortOrder));
}
}
}
每个实体类都有自己的配置类,但除了设置主键和支持字段的访问模式外,没有什么大不了的。
【问题讨论】:
-
tt可以是null这里是tt.ToolId -
这很明显,谢谢。我只是不确定如何解决它?由于我需要结果字典中的工具 ID,因此按它进行分组会消除在“let”行中的工具任务实体上使用 max 的可能性?
-
let 行使用空合并运算符“?”因此无法远程执行。
-
您可能需要改用
t.ToolId,因为已知 left 边不为空。当前的 EF Core 查询翻译中也存在一些缺陷,需要以特定方式编写 LINQ 查询,以使其完全翻译并在服务器端执行 - 例如,使用导航属性而不是手动连接,即编写方式聚合表达式等。为了给你一个具体的答案,我们需要看看你的实体模型。 -
如果我使用 t.ToolId,我将如何访问分组中的字段?我为模型添加了实体类,但从 cmets 和不必要的字段中删除了它。你还需要什么吗?
标签: c# entity-framework entity-framework-core ef-core-2.2