I have the two lists below where one comes from the database and the other from a JSON. The one from the database has it's Id associated.
List from database:
EmployeeId FirstName LastName EmployeeNumber
1234 Tom Cruise 98372829
5555 James Bond 93932228
The employeeId
is a GUID Saved in the database.
Now I retrieve a list of Employees again to detect changes - James Bond Lastname changed. And I used automapper to map in the same format as my database entity.
List from JSON:
EmployeeId FirstName LastName EmployeeNumber
000-0000... Tom Cruise 98372829
000-0000... James Carter 93932228
Now I want to update the first list with the FirstName
and LastName
based on the EmployeeNumber
.
// Employees retrieved in JSON
var retrievedEmployees = JsonSerializer.Deserialize<List<EmployeeDto>>(methodToRetrieveEmployees()))!.ToList();
var mappedEmployees = _mapper.Map<IEnumerable<Employee>>(retrievedEmployees);
var existingEmployeeFromDatabase = await GetExistingEmployees();
var employeesWithLatestUpdates = mappedEmployees
.Where(y => existingEmployeeFromDatabase.Any(z => z.Number == y.Number)).ToList();
So What I need to do is to update employeeswithLatestChanges
(Id,FirstName and LastName) with the values from existingEmployees
from the database. Since they don't have Id, this should be mapped by the EmployeeNumber
.
I have tried to use Union/joins but no luck.
CodePudding user response:
Updating by linq in c# 6
var updatedEmployee = employeeswithLatestChanges.Select(x => new Employee
{
FirstName = existingEmployees.FirstOrDefault(y => y.EmployeeId == x.EmployeeNumber)?.FirstName?? x.FirstName,
LastName = existingEmployees.FirstOrDefault(y => y.LastName == x.code)?.LastName ?? x.LastName ,
});
Can Use Loop also
foreach (var dbEmp in existingEmployees)
{
foreach(var emp in (employeeswithLatestChanges.Where(t => t.EmployeeNumber == dbEmp.EmployeeId)))
{
emp.FirstName= dbEmp.FirstName;
emp.LastName= dbEmp.LastName;
}
}
CodePudding user response:
To fix the idea we can assume the following class to represent an employee:
public sealed class Employee
{
public string FirstName { get; set; }
public string LastName { get; set; }
public Guid Id { get; set; }
public int Number { get; set; }
}
Suppose you have a collection of employees named employees
that you want to update by using another collection of employees named updatedEmployees
:
IEnumerable<Employee> employees = ....;
IEnumerable<Employee> updatedEmployees = ....;
The simplest way I can think of to solve your problem is the following:
public static void Main(string[] args)
{
// previous code omitted for brevity
Dictionary<int, Employee> employeeNumberToUpdatedEmployee = updatedEmployees.ToDictionary(x => x.Number);
foreach (var employee in employees)
{
if (employeeNumberToUpdatedEmployee.TryGetValue(employee.Number, out var updatedEmployee)
{
employee.FirstName = updatedEmployee.FirstName;
employee.LastName = updatedEmployee.LastName;
}
}
// subsequent code omitted for brevity
}
An alternative way to solve this problem is to perform a join operation by using LINQ to objects, as in the following code:
var employees = new List<Employee>
{
new Employee{ Id = Guid.NewGuid(), Number = 11, FirstName = "Bob", LastName = "Red" },
new Employee{ Id = Guid.NewGuid(), Number = 13, FirstName = "Alice", LastName = "Smith" },
new Employee{ Id = Guid.NewGuid(), Number = 5, FirstName = "Max", LastName = "Brown" },
};
var updatedEmployees = new List<Employee>
{
new Employee{ Id = Guid.NewGuid(), Number = 11, FirstName = "Bob", LastName = "Verdi" },
new Employee{ Id = Guid.NewGuid(), Number = 13, FirstName = "Alice", LastName = "Rossi" },
new Employee{ Id = Guid.NewGuid(), Number = 78, FirstName = "Sam", LastName = "Smith" },
};
// here we are using the fact that we can have, at most, one match
var query = from employee in employees
join updatedEmployee in updatedEmployees on employee.Number equals updatedEmployee.Number into matches
from match in matches.DefaultIfEmpty()
select new Employee
{
Id = employee.Id,
Number = employee.Number,
FirstName = match?.FirstName ?? employee.FirstName,
LastName = match?.LastName ?? employee.LastName,
};
foreach (var item in query)
{
Console.WriteLine($"{item.FirstName} {item.LastName}");
}