如何根据C#中的Ids填充嵌套列表中的数据?

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();

可以更好地工作.这是时间/内存权衡,但请注意,上述任何一个都比当前的查询超载更好.

点赞