简体   繁体   中英

EF Core Include childs after query with joins

I am using .Net Core 2.0 and EF Core. The following query is working fine but does not include the children.

What this query does is join:

  • Order
  • OrderItem and
  • Product

By multiplying the Quantity (in OrderItem) with the price (in Product), and doing the sum of this, I get the order total.

Now I am trying to include "OrderItem" and "Product" as I would like to see those in the final JSON of my web API. So getting the final JSON with all three entities and the summary of the total price for the order.

This is my repository:

public class OrderRepository : IOrderRepository
{
    private readonly BasketDbContext _basketDbContext;
    public OrderRepository(BasketDbContext basketDbContext)
    {
        _basketDbContext = basketDbContext;
    }

    public Order GetOrderById(int id)
    {
        return (from o in _basketDbContext.Orders
                join oi in _basketDbContext.OrderItems on new { o.Id } equals new { Id = oi.OrderId }
                join p in _basketDbContext.Products on new { oi.ProductId } equals new { ProductId = p.Id }
                where o.Id == id
                group new { o, p, oi } by new
                {
                    o.Id,
                    o.OrderDate
                }
            into g
                select new Order
                {
                    Id = g.Key.Id,
                    OrderDate = g.Key.OrderDate,
                    TotalPrice = g.Sum(p => p.p.Price * p.oi.Quantity)
                })
            .Include(x => x.OrderItems)
            .ThenInclude(y => y.Product)
            .FirstOrDefault();
    }
}

The includes in the method GetOrderById is not working, but I don't know how to include these in such query.

These are my models:

public class Order
{
    public int Id { get; set; }
    public DateTime OrderDate { get; set; }
    public decimal TotalPrice { get; set; }
    public List<OrderItem> OrderItems { get; set; }

    public decimal CalculateTotal()
    {
        return OrderItems.Sum(item => item.GetPrice());
    }
}

public class OrderItem
{
    public int Id { get; set; }
    [Required(ErrorMessage = "Empty OrderId")]
    public int OrderId { get; set; }
    [Required(ErrorMessage = "Empty ProductId")]
    public int ProductId { get; set; }
    [Required(ErrorMessage = "Empty Quantity")]
    [Range(1, 20, ErrorMessage = "Quantity must be between 1 to 20")]
    public int Quantity { get; set; }
    public Product Product { get; set; }

    public decimal GetPrice()
    {
        return Product.Price * Quantity;
    }
}

public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public decimal Price { get; set; }
}

Thanks!

The data you are getting in order is what you select in query. ie Id, OrderDate and TotalPrice:

select new Order
                {
                    Id = g.Key.Id,
                    OrderDate = g.Key.OrderDate,
                    TotalPrice = g.Sum(p => p.p.Price * p.oi.Quantity)
                })

If you want to map new order here (like id, orderDate etc) then you have to map "ItemOrder" and "Product" entities field by field as well.

I think you can simply return order without creating new order in query like:

return (from o in _basketDbContext.Orders where o.Id == id select o)
       .Include(x => x.OrderItems)
       .ThenInclude(y => y.Product)
       .FirstOrDefault();

TotalPrice calculation can be done on returned result.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM