我正在尝试投影相关数据,但是不断出错。
我有一个项目列表,每个项目可能有多个基准集(或没有),每个基准都包含多个里程碑。预计的项目列表应包含一个属性,该属性在最新设置的基准中包含特定的里程碑。
我的模型通过EFCore使用SQL:
private fun <T> any(): T {
Mockito.any<T>()
return uninitialized()
}
private fun <T> uninitialized(): T = null as T
在我的控制器中,我定义了投影类:
public class Project
{
public int ProjectID { get; set; }
public string Name { get; set; }
public ICollection<Baseline> Baselines { get; set; }
}
public class Baseline
{
public int BaselineID { get; set; }
public int ProjectID { get; set; }
public Project Project { get; set; }
public string Name { get; set; }
public DateTime DateSet {get; set;}
public string Description { get; set; }
public ICollection<BaselineDate> BaselineDates { get; set; }
}
public class BaselineDate
{
public int BaselineDateID { get; set; }
public int BaselineID { get; set; }
public Baseline Baseline { get; set; }
public int MilestoneTypeID { get; set; }
public MilestoneType MilestoneType { get; set; }
public DateTime Date { get; set; }
public string Comment { get; set; }
}
然后在一个函数中,我尝试使用efcore查询模型:
public class ProjectInfo
{
public int ProjectID { get; set; }
public string ProjectName { get; set; }
public DateTime? ProjectStart { get; set; }
}
public IList<ProjectInfo> ProjectInfoList { get; set; }
只要每个项目都有一个基准,此方法就可以正常工作。但是,当存在没有基准的项目时,将引发null异常。
ArgumentNullException:值不能为null。 参数名称:来源 System.Linq.Enumerable.Where(IEnumerable源,Func谓词)
我尝试添加.DefaultIfEmpty(new Baseline()),但会引发更多异常。
答案 0 :(得分:1)
请记住,Entity Framework将整个LINQ表达式转换为SQL(更准确地说,是 try 来做到这一点)。由于SQL中没有空引用的概念,因此您可以安全地使用在C#代码(或LINQ-to-objects)中会引发空引用异常的表达式。
但是除此之外,可以重写有问题的子查询,以便即使在LINQ-to-objects中,如果集合属性不为null,它也不会引发异常:
ProjectInfoList = await _context.Project
.Where(project => project.Branch == Branch)
.Select(project => new ProjectSummary
{
ProjectID = project.ProjectID,
ProjectName = project.Name,
ProjectStart = (from bl in project.Baselines
from bd in bl.BaselineDates
where bd.Comment == "Project Start"
orderby bl.DateSet descending, bd.Date descending
select (DateTime?)bd.Date).FirstOrDefault()
}
.AsNoTracking()
.ToListAsync();
我在查询语法中这样做是为了提高可读性。 from ... from
构造的方法语法为SelectMany
。 SelectMany
的语法在需要父级和子级都需要数据(bl.DateSet, bd.Date
)时非常尴尬。