EF核心包括()没有查询到所有儿童的
问题描述:
我有这样的模式:EF核心包括()没有查询到所有儿童的
public class RepairRequest
{
[Key]
public int Id { get; set; }
public List<RepairAction> RepairActions { get; set; }
public decimal TotalPrice => RepairActions.Sum(r => r.ActionPrice);
public string LastOperation => RepairActions.LastOrDefault().RepairOperation.Description;
}
public class RepairAction
{
[Key]
public int Id { get; set; }
public int RepairRequestId { get; set; }
public RepairRequest RepairRequest { get; set; }
public int RepairOperationId { get; set; }
public RepairOperation RepairOperation { get; set; }
public decimal ActionPrice { get; set; }
}
public class RepairOperation
{
[Key]
public int Id { get; set; }
public string Description { get; set; }
}
我想查询RepairRequests并获得TotalPrice也LastOperation的清单,但对于这两个属性不起作用。这是我迄今为止所尝试的:
using (var context = new ServiceManagerContext(new DbContextOptions<ServiceManagerContext>())) {
var data = context.RepairRequests
.Include(r => r.RepairActions).ThenInclude(r => r.RepairOperation); // Only LastAction works
//.Include("RepairActions").Include("RepairActions.RepairOperation"); // Only LastAction works
//.Include(r => r.RepairActions); // Only TotalPrice works
//.Include("RepairActions"); // Only TotalPrice works
var repairRequest = data.FirstOrDefault(r => r.Id == 5);
Assert.NotNull(repairRequest);
Assert.Equal(60.0m, repairRequest.RepairPrice);
Assert.Equal("Παραδόθηκε", repairRequest.LastAction);
}
谢谢。
答
我会考虑尝试避免在您的域实体中解析计算的属性,而是在查询数据以填充视图模型时查找这些属性。
如果您的视图模型需要TotalPrice和LastOperation,然后提供一个存储库或此类返回的IQueryable可以展开查询返回所需要的使用延迟执行,而不是试图依靠预先加载整个树:
即,也就是说
IQueryable<RepairRequest> requests = context.RepairRequests.Where(x => x.Id == 5); // Or pull from a Repository returning the IQueryable
var viewModelData = requests.Select(x => new {x.Id, TotalPrice = x.RepairActions.Sum(), LastOperation = x.RepairActions.LastOrDefault()?.RepairOperation?.Description }).SingleOrDefault();
这应该执行一个更优化的查询,并返回一个匿名类型只需要填入你想显示什么视图模型的数据。 iffy位是在没有修复操作的情况下,或者是没有操作的修复操作.EF应该避免null ref,并且只返回null。这个?语法可能不是必需或支持的,所以它可能只需要“。”。使用一种方法,你急于或懒惰地加载这些相关的实体并将Linq从实体实例中删除,注意.SingleOrDefault()并深入到子字段中。
答
Firstaball必须声明外键和标志虚拟财产,如:
public class RepairRequest
{
[Key]
public int Id { get; set; }
public virtual ICollection<RepairAction> RepairActions { get; set; }
public decimal TotalPrice => RepairActions.Sum(r => r.ActionPrice);
public string LastOperation => RepairActions.LastOrDefault().RepairOperation.Description;
}
public class RepairAction
{
[Key]
public int Id { get; set; }
public decimal ActionPrice { get; set; }
public int RepairRequestId { get; set; }
[ForeignKey("RepairRequestId ")]
public virtual RepairRequest RepairRequest { get; set; }
public int RepairOperationId { get; set; }
[ForeignKey("RepairOperationId")]
public RepairOperation RepairOperation { get; set; }
}
然后,你可以调用该方法,它加载所有的孩子值:
var data = context.RepairRequests.Include("RepairActions.RepairOperation");
'LastAction'或'LastOperation'?你将它们混淆 – GGO
LastOperation。抱歉。 – dseferlis
请始终明确指出您正在使用的是哪个版本。 ESP。 ef-core在过去一直在迅速发展。 –