多对一外键,循环多个时返回总计一

问题描述 投票:0回答:1

我有一个购物车,但在存储订单方面遇到了一些问题。

我的逻辑是 - 我有 2 个订单表:

订单.cs

public class Order
{
    public int Id { get; set; }

    public string UserName { get; set; }

    public bool Shipped { get; set; } = false;

    [Column(TypeName = "decimal(8,2)")]
    public decimal GrandTotal { get; set; }

    public DateTime DateTime { get; set; } = DateTime.Now;

}

OrderDetail.cs

public class OrderDetail
{
    public int Id { get; set; }

    public long ProductId { get; set; }

    public string ProductName { get; set; }

    public int Quantity { get; set; }

    [Column(TypeName = "decimal(8,2)")]
    public decimal Price { get; set; }

    public string Image { get; set; }

    public int OrderId { get; set; }
    public Order Order { get; set; }
}

如您所见,我在它们之间建立了外键关系,效果很好,我在控制器中获取数据的方式是:

List<OrderDetail> orderDetails = await _context.OrderDetails.OrderByDescending(x => x.Id).Where(x => x.Order.UserName == username).Include(x => x.Order).ToListAsync();

这也工作得很好,问题是当我循环浏览视图中的列表时,对于

OrderDetail
中的每个项目,我也(当然)打印出
Order
但是我想打印
Order
只有一次,我该怎么办?

View(我显然循环遍历整个过程并每次重复 Order,但我不知道如何不这样做)

foreach (var item in Model)
{
    @item.ProductName <br />
    @item.Quantity <br />
    @item.Price <br />
    @item.Image <br />
    // I want the code below **once**
    @item.Order.GrandTotal <br />
    @item.Order.DateTime <br />
    @item.Order.Shipped <br />
}

我想我可以在控制器中获取订单信息并将其传递到视图,但是如果我有同一用户名的多个订单怎么办,这是主要问题。

c# entity-framework asp.net-core
1个回答
0
投票

两个选项:更新您的订单实体以包含 OrderDetails 列表:

public virtual ICollection<OrderDetail> OrderDetails {get; protected set; } = new List<OrderDetail>();

...并配置关系以便订购

.HasMany(o => o.OrderDetails)
.WithOne(od => od.Order);

然后更新视图的模型以使用 Order 而不是 OrderDetails 的集合。您获取订单及其详细信息并将其提供给视图:

var order = context.Orders
    .Include(o => o.OrderDetails)
    .Single(o => o.OrderId == orderId);

在视图中,您可以使用订单,然后迭代其详细信息:

foreach (var item in Model.OrderItems)
{
    @item.ProductName <br />
    @item.Quantity <br />
    @item.Price <br />
    @item.Image <br />
}
Model.GrandTotal <br />
Model.DateTime <br />
Model.Shipped <br />

选项 2 是使用投影来构造视图实际需要的数据。在视图中不需要所有列的情况下传递整个 Order 和 OrderDetails。这涉及创建视图模型:

[Serializable]
public class OrderViewModel
{
    public int OrderId { get; set; }
    public decimal GrandTotal { get; set; }
    public DateTime DateTime { get; set; }
    public bool Shipped { get; set; }

    public ICollection<OrderDetailViewModel> { get; set; } = new List<OrderDetailViewModel>();
}

[Serializable]
public class OrderDetailViewModel
{
    public int OrderDetailId { get; set; }
    public string ProductName { get; set; }
    public int Quantity { get; set; }
    public decimal Price { get; set; }
    public string Image { get; set; }
}

然后阅读时:

var order = context.Orders
    .Where(o => o.OrderId == orderId)
    .Select(o => new OrderViewModel
    {
        OrderId = o.OrderId,
        GrandTotal = o.GrandTotal,
        DateTime = o.DateTime,
        Shipped = o.Shipped,
        OrderDetails = o.OrderDetails
            .Select(od => new OrderDetailViewModel
            {
                OrderDetailId = od.OrderDetailId,
                ProductName = od.ProductName,
                Quantity = od.Quantity,
                Price = od.Price,
                Image = od.Image
            }).ToList()
    }).Single();

这种方法的优点是,它可以避免加载不必要的数据,并且使数据“安全”地发送到视图,以防视图 JavaScript 可能想要反序列化模型数据。它还允许您格式化值、根据需要展平数据等以适应视图。

© www.soinside.com 2019 - 2024. All rights reserved.