Linq to sql 通过一对多查找优化Linq到Sql的映射
我在使用以下数据结构优化数据查找时遇到问题:Linq to sql 通过一对多查找优化Linq到Sql的映射,linq-to-sql,database-design,optimization,orm,entity-relationship,Linq To Sql,Database Design,Optimization,Orm,Entity Relationship,我在使用以下数据结构优化数据查找时遇到问题: Order ----- Id Customer Date ... etc OrderStatus ------ Id OrderId Date UpdatedBy StatusTypeId ...etc 这让我在订单列表页面感到头疼,该页面基本上显示了一个订单列表。列表中的每个订单摘要显示了来自订单和当前订单状态的一系列字段,即带有最新日期的订单状态,链接到订单 Order List --------------------------
Order
-----
Id
Customer
Date
... etc
OrderStatus
------
Id
OrderId
Date
UpdatedBy
StatusTypeId
...etc
这让我在订单列表页面感到头疼,该页面基本上显示了一个订单列表。列表中的每个订单摘要显示了来自订单
和当前订单状态
的一系列字段,即带有最新日期的订单状态
,链接到订单
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 |
-------------------------------------------------------
现在,假设我想列出今年的所有订单。我的存储库获取顺序
对象
var orders=\u 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();
}
Order
-----
Id
Customer
Date
CurrentStatusTypeId
CurrentStatusDate
CurrentStatusUpdatedBy
...etc
OrderStatusHistory
------
Id
OrderId
Date
UpdatedBy
StatusTypeId
...etc
因此,对于返回的每个订单
,我最后得到的是SELECT
语句,然后是SELECT
语句,该语句位于OrderStatus
因此,要显示今年所有记录的摘要,需要大约20000个单独的SQL查询,并且需要花费许多分钟来加载
有什么好办法解决这个问题吗
我正在考虑重新编写数据库,以便在Order
表中保存当前的OrderStatus
,因此我最终得到了如下结果
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();
}
Order
-----
Id
Customer
Date
CurrentStatusTypeId
CurrentStatusDate
CurrentStatusUpdatedBy
...etc
OrderStatusHistory
------
Id
OrderId
Date
UpdatedBy
StatusTypeId
...etc
这是我能看到的解决问题的唯一方法,但似乎是一个相当糟糕的解决方案
这里最好的方法是什么?您可以创建DataLoadOptions对象,如下所示:
DataContext db = new DataContext
DataLoadOptions ds = new DataLoadOptions();
ds.LoadWith<OrderStatus>(c => c.Orders);
db.LoadOptions = ds;
DataContext db=newdatacontext
DataLoadOptions ds=新的DataLoadOptions();
ds.LoadWith(c=>c.Orders);
db.LoadOptions=ds;
然后,当您运行查询时,它应该预取OrderStatus表请不要为了解决问题而对数据库模型进行反规范化。这只会让事情变得更糟。您可以通过编写一个服务方法来解决这个问题,该方法返回数据传输对象(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();
}
注意以下几点:
- 此代码将作为数据库中的单个SQL查询执行
- 此方法将返回一个仅包含客户端所需数据的对象,但仅此而已。无
客户
对象,无订单状态
对象
- 通过调用
ToArray
,我们可以确保在此时查询数据库,并且不会延迟
这三点确保了性能的最大化,并允许服务层控制对数据库执行的操作
我希望这会有所帮助。这确实提高了性能,但仍有改进的余地LoadWith
将从数据库中获取每个订单的所有OrderStatus
记录,而每个订单只需要最后一个OrderStatus
。这有点帮助,但没有帮助。我知道我需要做这样的事情,但它充满了问题。我的订单对象位于域层。我的OrderSummary对象是演示层中ViewModel的一部分。我的OrderRepository甚至不知道OrderSummary存在。我的OrderRepository封装了一个通用的Linq响应库,这给了我相当有限的控制。我使用的是DTO,但除了使用GetCurrentStatus()方法返回Order对象(这是我自己的Order类,不是Linq生成的类)之外,我仍然无法返回太多。您可以将OrderSummary
移动到服务层,或者定义一个DTO并将其映射到表示层中的ViewModel。您需要在此级别使用DTO以获得良好的性能。如果您的存储库有限,也许您应该采取不同的方法。例如,在存储库上实现IQueryable。在这里寻找灵感:。