如何基于EmployeeNumber合并两个对象列表并更新数据?
员工列表更新需求与解决方案
场景说明
我有两个员工列表:
- 数据库来源列表(关联
EmployeeId,为GUID类型):
| EmployeeId | FirstName | LastName | EmployeeNumber |
|---|---|---|---|
| 1234 | Tom | Cruise | 98372829 |
| 5555 | James | Bond | 93932228 |
- JSON来源列表(James Bond的姓氏已修改为Carter,
EmployeeId为无效值):
| EmployeeId | FirstName | LastName | EmployeeNumber |
|---|---|---|---|
| 000-0000... | Tom | Cruise | 98372829 |
| 000-0000... | James | Carter | 93932228 |
需求:基于EmployeeNumber匹配,用数据库列表中的Id、FirstName、LastName更新JSON映射后的列表数据。
当前尝试的代码
// 从JSON获取员工列表 var retrievedEmployees = JsonSerializer.Deserialize<List<EmployeeDto>>(methodToRetrieveEmployees()))!.ToList(); // 通过AutoMapper映射为数据库实体格式 var mappedEmployees = _mapper.Map<IEnumerable<Employee>>(retrievedEmployees); // 从数据库获取现有员工 var existingEmployeeFromDatabase = await GetExistingEmployees(); // 筛选出两边都存在的员工(仅匹配,未更新) var employeesWithLatestUpdates = mappedEmployees .Where(y => existingEmployeeFromDatabase.Any(z => z.Number == y.Number)).ToList();
尝试过Union/Join但未成功,需要可行的解决方案。
解决方案
方案1:遍历更新原对象(推荐,保留原引用)
将数据库列表转为字典提升匹配效率,然后逐个更新映射后的员工对象:
// 从JSON获取并映射为实体列表 var retrievedEmployees = JsonSerializer.Deserialize<List<EmployeeDto>>(methodToRetrieveEmployees()))!.ToList(); var mappedEmployees = _mapper.Map<List<Employee>>(retrievedEmployees); // 将数据库员工转为字典,以EmployeeNumber为键,减少匹配耗时 var dbEmployeeMap = (await GetExistingEmployees()) .ToDictionary(emp => emp.EmployeeNumber); // 遍历映射列表,匹配数据库数据并更新字段 foreach (var mappedEmp in mappedEmployees) { if (dbEmployeeMap.TryGetValue(mappedEmp.EmployeeNumber, out var dbEmp)) { mappedEmp.EmployeeId = dbEmp.EmployeeId; mappedEmp.FirstName = dbEmp.FirstName; mappedEmp.LastName = dbEmp.LastName; // 若有其他需要同步的字段,可在此添加 } } // mappedEmployees即为更新后的最终列表 var employeesWithLatestUpdates = mappedEmployees;
方案2:用LINQ Join生成新对象
如果不需要保留原映射对象的引用,可以直接通过Join生成更新后的新列表:
var retrievedEmployees = JsonSerializer.Deserialize<List<EmployeeDto>>(methodToRetrieveEmployees()))!.ToList(); var mappedEmployees = _mapper.Map<IEnumerable<Employee>>(retrievedEmployees); var existingEmployeeFromDatabase = await GetExistingEmployees(); var employeesWithLatestUpdates = mappedEmployees .Join( existingEmployeeFromDatabase, mappedEmp => mappedEmp.EmployeeNumber, dbEmp => dbEmp.EmployeeNumber, (mappedEmp, dbEmp) => new Employee { EmployeeId = dbEmp.EmployeeId, FirstName = dbEmp.FirstName, LastName = dbEmp.LastName, EmployeeNumber = mappedEmp.EmployeeNumber, // 其他字段根据需求选择从mappedEmp或dbEmp取值 } ) .ToList();
方案说明
- 方案1适合需要保留原映射对象引用的场景,且字典匹配的效率远高于多次
Any遍历,数据量越大优势越明显。 - 方案2通过LINQ直接生成新对象,代码更简洁,但会丢弃原映射对象的引用。
- 两种方案都严格基于
EmployeeNumber匹配,确保用数据库的最新Id、FirstName、LastName覆盖JSON映射的数据。
内容的提问来源于stack exchange,提问作者Vida
相关产品推荐
相关产品推荐

