我有一张包含客户列表的表格。 一个客户有0个,1个或更多的合同。
我必须检索所有已启用的客户,在DTO中设置它们并将当前合同添加到此DTO(如果有)
目前,它非常缓慢(超过10分钟)。
CODE
1777: '23.5R25 Bridgestone VLT **',
答案 0 :(得分:2)
使用投影仅使用"选择"返回您使用的列。如果您有36列,这将为您提供更好的结果。
customers= context.Customers.Where(c => c.IsEnabled).Select(cust => new Customer
{
Id = cust .Id
}).ToList();
https://www.talksharp.com/entity-framework-projection-queries
之后检查查询计划是否有表扫描或索引扫描。尽量通过设置适当的索引来避免它们。
答案 1 :(得分:1)
我认为问题是在循环中检索契约的查询。最好用一个查询检索所有数据,如下所示:
var date = DateTime.Today;
var query =
from customer in context.Customers
where customer => customer.IsEnabled
select new
{
customer,
contract = customer.Contracts.FirstOrDefault(c => c.ContractEndDate >= date && c.ContractStartDate <= date)
};
var result = new List<CustomerOverviewDto>();
foreach (var entry in query)
{
CustomerOverviewDto customerDto = GetCustomer(entry.customer);
if (entry.contract != null)
SetContract(customerDto, entry.contract);
result.add(customerDto);
}
答案 2 :(得分:0)
好的,首先,当你使用.ToList()时,你正在那里执行查询,并将IsEnabled的每一行拉回到内存中进行处理。你想在数据库方面做更多的事情。
result = context.Customers.Where(c => c.IsEnabled); //be lazy
其次,如果查询具有可以使用的索引,那么查询只会很好地执行并由执行引擎进行优化。
在您正在执行比较的字段上添加一些索引。
想想这行代码
customer.Contracts.Where(c => c.ContractEndDate >= DateTime.Today &&
c.ContractStartDate <= DateTime.Today).FirstOrDefault();
您是否拥有从客户到合同的外键,并且您在ContractStartDate和ContractEndDate上没有索引,它将执行非常糟糕的操作并且将为每个客户运行一次&#39;的IsEnabled&#39;
答案 3 :(得分:0)
似乎你只想在返回值时做一些事情。因此,您可以在初始查询中添加此项,并包含合同:
customers= context.Customers
.Include(c => c.Contracts)
.Where(c => c.IsEnabled
&& c.Contracts.Any(con => con.ContractEndDate >= DateTime.Today && con .ContractStartDate <= DateTime.Today))
.ToList();
foreach (Customer customer in customers)
{
CustomerOverviewDto customerDto = GetCustomer(customer);
Framework.Contract contract =
customer.Contracts.Where(c => c.ContractEndDate >= DateTime.Today && c.ContractStartDate <= DateTime.Today)
.First();
SetContract(customerDto, contract);
}
答案 4 :(得分:0)
由于我不知道您的域模型结构是什么样的,或者您没有使用导航属性将CURRENT合同映射到客户,因此您可以执行类似的操作。
通过实现所有客户和合同,然后将内存映射到DTO对象,您可以只对数据库进行2次往返。假设您将CustomerId设置为FK,将Customer.Id设置为PK。
List<CustomerOverviewDto> result = new List<CustomerOverviewDto>();
customers = context.Customers.Where(c => c.IsEnabled).ToList();
contracts = context.Contracts.Where(c => c.ContractEndDate >= DateTime.Today && c.ContractStartDate <= DateTime.Today).ToList();
foreach (Customer customer in customers)
{
var customerDto = GetCustomer(customer);
var contract = contracts.Where(c => c.CustomerId == customer.Id).FirstOrDefault();
if (contract != null)
{
SetContract(customerDto, contract);
}
result.add(customerDto);
}
答案 5 :(得分:0)
我终于通过使用1个查询和投影解决了这个问题
context.Customers.Where(c => c.IsEnabled).Select(c => new CustomerOverviewDto{...}).ToList();
我在创建CustomerOverviewDto时直接检索合约