我在使用以下数据结构优化数据查找时遇到了问题:
Order
-----
Id
Customer
Date
... etc
OrderStatus
------
Id
OrderId
Date
UpdatedBy
StatusTypeId
...etc
这导致我在订单列表页面上头疼,该页面基本上显示了Orders
的列表。列表中的每个订单摘要都会显示来自Order
和当前OrderStatus
的一系列字段,即OrderStatus
,其中包含最新的Date
字段已链接到Order
。
Order List
-------------------------------------------------------
Order Id | Customer | Order Date | CurrentStatus |
-------------------------------------------------------
1 | Someone | 1.10.2010 | Completed |
-------------------------------------------------------
2 | Someone else | 12.10.2010 | In Progress |
-------------------------------------------------------
3 | Whoever | 17.10.2010 | On Hold |
-------------------------------------------------------
现在,我想列出今年的所有订单。我的存储库提取Order
个对象
var orders = _repository.GetAllOrdersSinceDate(dt);
现在我最终得到像
这样的东西foreach (Order order in orders)
{
OrderSummary summary = new OrderSummary();
summary.Customer = order.Customer;
summary.Date = order.Date;
// ...etc
// problem here!!
summary.OrderStatus = order.OrderStatus
.OrderByDescending(s => status.Date).First();
}
所以我最终得到的是SELECT
上的Order
声明,然后SELECT
声明了OrderStatus
对于每个Order
返回的声明。
因此,要显示今年所有记录的摘要,需要大约20,000个单独的SQL查询,并需要花费很多分钟才能加载。
有没有任何巧妙的方法来解决这个问题?
我正在考虑重新编写数据库,以便在OrderStatus
表格中保留当前 Order
,所以我最终会得到类似
Order
-----
Id
Customer
Date
CurrentStatusTypeId
CurrentStatusDate
CurrentStatusUpdatedBy
...etc
OrderStatusHistory
------
Id
OrderId
Date
UpdatedBy
StatusTypeId
...etc
这是我能看到解决问题的唯一方法,但似乎是一个非常讨厌的解决方案。
这是前进的最佳方式吗?
答案 0 :(得分:1)
请不要对数据库模型进行非规范化以解决您的问题。这只会让事情变得更糟。您可以通过编写一个返回数据传输对象(DTO)列表而不是LINQ to SQL实体的服务方法来解决此问题。例如,服务方法可能如下所示:
public OrderSummary[] GetOrderSummariesSinceDate(DateTime d)
{
return (
from order in this.context.Orders
where order.Date >= d
let lastStatus = (
from status in order.OrderStatusses
orderby status.Date descending
select status).First()
select new OrderSummary
{
OrderId = order.Id,
CustomerName = order.Customer.Name,
Date = order.Date,
OrderStatus = lastStatus.StatusType.Name
}).ToArray();
}
请注意以下事项:
Customer
个对象,没有OrderStatus
个对象。ToArray
,我们确保此时查询数据库并且不会延迟。这三点可确保性能最大化,并允许服务层保持对数据库执行内容的控制。
我希望这会有所帮助。
答案 1 :(得分:0)
您可以按如下方式创建DataLoadOptions对象:
DataContext db = new DataContext
DataLoadOptions ds = new DataLoadOptions();
ds.LoadWith<OrderStatus>(c => c.Orders);
db.LoadOptions = ds;
然后当您运行查询时,它应该预取OrderStatus表