Passing List of KeyValuePairs to LINQ query and selecting the Value for the Key that matches the entity's Id

Viewed 68

What is the best way to solve this?

TL;DR version:

Using LINQ and EntityFramework I am trying to pass in a List of KeyValuePairs to a LINQ query, then for each entity who's ID matches any Key in the list, selecting a new column with that key's value.

So if my KeyValuePairs are

List<KeyValuePair(int, long)> keyValuePairs = new() 
{
    new(1, 10),
    new(2, 20),
    new(3, 30)
}

where the key is an EmployeeId and the value is a CompanyId,

and I'm querying an Employees table, with two columns, Id and Name,

and my EmployeeModel class is

public int Id;
public int Name;
public long CompanyId;

I want to do something like this:

var keys = keyValuePairs.Select(x => x.Key);

IQueryable<EmployeeModel> EmployeeModels = Db.Employees
    .Where(e => keys.Contains(p.Id))
    .Select(e => new EmployeeModel 
    {
        Id = e.Id,
        Name = e.Name,
        CompanyId = keyValuePairs.Where(x => x.Key == e.Id).Select(x => x.Value).First()
    });

Currently I get this exception:

The LINQ expression 'x' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to 'AsEnumerable', 'AsAsyncEnumerable', 'ToList', or 'ToListAsync'.

I want to avoid loading this into memory because the results could potentially be hundreds of thousands. In addition, I need to pass the result into a method that requires an IQueryable

More context for understanding what I'm trying to do (and maybe someone can see if this is an x-y problem):

I have two Databases Database A has a Table called Companies and a join table called CompanyEmployees

Database B has a Table called Employees The Employee table has a column for Employee Id, but no column for Company Id

My EmployeeModel class however, has a prop for the CompanyId of the company to which the employee belongs. I'm trying to load a list of employees, and selecting a EmployeeModel which includes the CompanyId

The way I'm trying to accomplish that is loading into memory a List of KeyValuePairs where the Key = CustomerEmployee.EmployeeId and the Value = CustomerEmployee.CustomerId and then using that List to Query the other Db. (I don't see any alternative to loading the List of KeyValuePairs into memory, even though I'd obviously rather not)

1 Answers

Also you probably have a problem with this part:

CompanyId = keyValuePairs.Where(x => x.Key == e.Id).Select(x => x.Value)

As CompanyId is a long, and the result of your Linq expression is a IEnumerable. If you're sure you have a result and only one, then you may use:

CompanyId = keyValuePairs.Where(x => x.Key == e.Id).Select(x => x.Value).First()
Related