EF Core Include()不查询所有子项

时间:2017-10-13 08:17:30

标签: entity-framework

我有这个型号:

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并在List中获取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);
}

谢谢。

2 个答案:

答案 0 :(得分:1)

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");

答案 1 :(得分:1)

我考虑避免尝试解析域实体中的计算属性,而是在查询数据以填充视图模型时尝试解决这些问题。

如果您的视图模型需要TotalPrice和LastOperation,那么提供一个Repository或返回的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。 ?。语法可能不是必需的或不受支持的,因此可能只需要&#34;。&#34;。使用您渴望或延迟加载这些相关实体并从实体实例执行Linq的方法,请小心.SingleOrDefault()并向下钻取到子字段。