简体   繁体   中英

Load collection except another collection using linq

I have this search method:

public List<Employeees> AutoSuggestEmployeee(string keyword,
    long employeeeTypeId, int count)
{
    return context.Employeees.Where(
        x => x.EmployeeeName.Contains(keyword)
        && x.EmployeeeTypeId == employeeeTypeId)
    .Take(count).ToList();
}

I have another collection of Employeees, say "BadEmployeees", what I want is using the same previous method to return all Employeees except "BadEmployeees".

I tried to write it like this:

return context.Employeees.Where(
        x => x.EmployeeeName.Contains(keyword)
        && x.EmployeeeTypeId == employeeeTypeId)
    .Except(BadEmployeees).Take(count).ToList();

But it is giving an exception that Except can just work with data types such as Int, Guid,...

The Except method does a comparison, so it has to know how to compare the objects. For simple types there are standard comparisons, but for complex types you need to supply an equality comparer that compares the relevant data in the object.

Example:

class EmployeeComparer : IEqualityComparer<Employeees> {

  public bool Equals(Employeees x, Employeees y) {
    return x.Id == y.Id;
  }

  public int GetHashCode(Employeees employee) {
    return employee.Id.GetHashCode();
  }

}

Usage:

return
  context.Employeees
  .Where(x => x.EmployeeeName.Contains(keyword) && x.EmployeeeTypeId == employeeeTypeId)
  .Except(BadEmployeees, new EmployeeComparer())
  .Take(count)
  .ToList();

If you're happy to retrieve all the data and then perform the "except", that's relatively easy:

return context.Employees
              .Where(x => x.EmployeeName.Contains(keyword)
                          && x.EmployeeTypeId == employeeeTypeId)
              // Limit the data *somewhat*
              .Take(count + BadEmployees.Count)
              // Do the rest of the query in-process
              .AsEnumerable()
              .Except(BadEmployees)
              .Take(count)
              .ToList();

Alternatively:

// I'm making some assumptions about property names here...
var badEmployeeIds = badEmployees.Select(x => x.EmployeeId)
                                 .ToList();

return context.Employees
              .Where(x => x.EmployeeName.Contains(keyword)
                          && x.EmployeeTypeId == employeeeTypeId)
                          && !badEmployeeIds.Contains(x.EmployeeId))
              .Take(count)
              .ToList();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM