我有一个购物车,但在存储订单方面遇到了一些问题。
我的逻辑是 - 我有 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 />
}
我想我可以在控制器中获取订单信息并将其传递到视图,但是如果我有同一用户名的多个订单怎么办,这是主要问题。
两个选项:更新您的订单实体以包含 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 可能想要反序列化模型数据。它还允许您格式化值、根据需要展平数据等以适应视图。