public class CarDTO
{
public int CarId { get; set; }
public string CarName { get; set; }
public List<PolicySummaryDTO> PolicySummaries { get; set; }
}
public class PolicySummaryDTO
{
public long PolicyId { get; set; }
public string PolicyName { get; set; }
public decimal Amount { get; set; }
}
我有List< CarDTO>汽车每辆车都已列出政策清单< PolicySummaryDTO> PolicySummaries.
PolicyId已填满.但其他属性如PolicyName,Amount等则不是.
我需要做的是从DB _contex.PolicySummary获取数据,我需要完成缺少的字段.
我知道我可以这样做.
>获取所有PolicyIds
var policyIds = cars.SelectMany(t => t.PolicySummaries).Select(r => r.PolicyId);
>根据ID获取PolicyData
var policyData = _context.PolicySummary.Where(t => policyIds.Contains(t.PolicyId));
>然后使用foreach我可以填充数据.
foreach (var car in cars)
{
foreach (var policy in car.PolicySummaries)
{
var policyDataToUse = policyData.Single(t => t.PolicyId == policy.PolicyId);
policy.Amount = policyDataToUse.Amount;
policy.PolicyName = policyDataToUse.PolicyName;
}
}
Everthing工作正常,但我想知道我是否能以更优雅的方式做到这一点,也许以某种方式使用LINQ JOIN或其他东西,或者我的解决方案是完全正确的?
编辑 – 字典解决方案
var policyIds = cars.SelectMany(t => t.PolicySummaries).Select(r => r.PolicyId);
var policyDict = _context.PolicySummary.Where(t => policyIds.Contains(t.PolicyId)).ToDictionary(t => t.PolicyId);
foreach (var car in cars)
{
foreach (var policy in car.PolicySummaries)
{
var policyDataToUse = policyDict[policy.PolicyId];
policy.Amount = policyDataToUse.Amount;
policy.PolicyName = policyDataToUse.PolicyName;
}
}
最佳答案 首先,为什么数据没有填写?您应该能够在使用.Include从DB中实际取车期间填写任何相关实体中的数据.
var carEntity = _context.Cars.Where(predicate).Include(c => c.PolicySummaries).Single();
其次,您的代码存在严重的性能问题:policyData是IQueryable.每次执行policyData.Single时,都会向数据库发送一个新查询,查看所有策略,过滤那些在policyIds中具有其ID的策略并选择适当的策略.如果有许多策略,这将是非常低效的 – 每个foreach迭代都是一个新查询!你应该做的事情可能是这样的:
var policyData = _context.PolicySummary.Where(t => policyIds.Contains(t.PolicyId)).ToList();
获取所有相关政策.如果存在大量共享策略并且最终在某些时候最终加载大部分策略,这也可能效率低下,因此如果数据库中没有十亿个策略:
var policies = _context.PolicySummary.ToList();
可以更好地工作.这是时间/内存权衡,但请注意,上述任何一个都比当前的查询超载更好.