I have this code to select the city for each person whose Id matches from the list of cities:
public List<PersonelDto> MapPersonelDto(List<Personel> personels,List<City> cities)
{
var result = new List<PersonelDto>();
foreach (var item in personels)
{
var personel = new PersonelDto
{
Id = item.Id,
Maaş = item.Salary,
MedeniHal = item.MartialStatus,
Meslek = item.Job,
Soyisim = item.LastName,
Şehir = (from s in cities where s.Id == item.CityId select s.name).ToString()
};
result.Add(personel);
}
return result;
}
But City's value come out like this:
System.Linq.Enumerable WhereSelectListIterator`2[Personnel_Registration.City,System.String]
How can I fix this?
CodePudding user response:
The error is because there's nothing in the type system metadata to guarantee you won't have more than one city match, and so the result of the expression is a potential collection of 0, 1, or more cities. What you see is the result of calling .ToString()
on that collection.
To fix it, you can do this:
public IEnumerable<PersonelDto> MapPersonelDto(IEnumerable<Personel> personels, IEnumerable<City> cities)
{
return personels.Select( p => {
new PersonelDto() {
Id = item.Id,
Maaş = item.Salary,
MedeniHal = item.MartialStatus,
Meslek = item.Job,
Soyisim = item.LastName,
Şehir = string.Join(",", cities.Where(c => c.Id == p.CityId).Select(c=> c.name));
}
});
}
Or, if you're confident you only want one city, you could do this:
public IEnumerable<PersonelDto> MapPersonelDto(IEnumerable<Personel> personels, IEnumerable<City> cities)
{
return personels.Select( p => {
new PersonelDto() {
Id = item.Id,
Maaş = item.Salary,
MedeniHal = item.MartialStatus,
Meslek = item.Job,
Soyisim = item.LastName,
Şehir = cities.FirstOrDefault(c => c.Id == p.CityId)?.name;
}
});
}
Note the complete lack of Lists. You really ought to get out of the habit of using List<T>
everywhere, and instead let things remain as an IEnumerable<T>
as much as possible. This can make your code faster and MUCH more efficient with RAM use.
Another benefit is it makes your code more flexible. For example, you can still pass the existing Lists to this new method. And if for some reason you need the result to be a List<>
for the next method call (hint: you probably don't really need this at all) you can always add a .ToList()
after calling the method. But, again, don't do that unless you really have to!
CodePudding user response:
from s in cities where s.Id == item.CityId select s.name
return an IEnumerable - there might be more than one city
do instead
Şehir = (from s in cities where s.Id == item.CityId select s.name).FirstOrDefault().ToString()
which selects the first element
Note that this assumes that there is always a matching city. If not then you should supply a default value
Şehir = (from s in cities where s.Id == item.CityId select s.name).FirstOrDefault("unknow city").ToString()