Reputation: 943
I have a list on my UI for which the user can customize the columns to be displayed. The data for this list is being fetch from a Linq query with 10 joins which is considerably expensive. I am using Entity Framework Core 2. I would like to see if there's a way to dynamically add the joins to the query according to the specific sets of columns that user has chosen to be displayed on the list OR the filtering that has been applied to the list on the client.
For example take following query:
SELECT a.Id, a.Code, a.Sector, ad.City, ad.Country, u.FullName
FROM Accounts a
INNER JOIN Addresses ad on ad.Account = a.Id
INNER JOIN Users u ON u.Id = a.AccountManager
WHERE ad.Country = 'NL'
And this is my Linq
public IEnumerable<Account> Get(QueryClause<Account> queryClause, out ForGetCollectionOptions forGetCollectionOptions)
{
using (_dbContext)
{
var result = (
from account in _dbContext.Accounts
join address in _dbContext.Addresses on account.ID equals address.Account into address_
from address__ in address_.DefaultIfEmpty()
join user in _dbContext.Users on account.AccountManager equals user.Id into user_
from user__ in user_.DefaultIfEmpty()
select new Account
{
Id = account.ID,
Code = account.Code.Trim(),
Sector = account.Sector.Trim(),
City = address__.City,
Country = address__.Country,
AccountManager = user__.FullName
}
);
//Filtering
ApplyFilterClause(ref result, queryClause.FilterClause);
}
return result.toList();
}
If the user choose to only see the columns Code and Sector of each account, I wouldn't need to include the joins to the addresses nor to the users
If the user choose to only see the columns code and sector and filter based on country, I would only need to include the join to addresses but I wouldn't need to include the join to the users table.
Is there a generic way that I could implement this logic?
For example if I were to send the parameter to my API such as ...&Select="Code,City"
I would exclude the joins to Addresses and Users
Upvotes: 0
Views: 1175
Reputation: 380
If you have bad performance with the joins you just have to make sure that the condition is false when you don't need the information of the table.
For example, if you don't need users information you can do something like this:
DECLARE @UsersNeeded bit=0;
SELECT * FROM Accounts a
LEFT JOIN Addresses ad on ad.Account = a.Id
LEFT JOIN Users u ON
@UsersNeeded=1 and u.Id = a.AccountManager
WHERE ad.Country = 'NL'
Linq will be something like this:
var usersNeeded = false;
from account in _dbContext.Accounts
join address in _dbContext.Addresses on account.ID equals address.Account into address_
from address__ in address_.DefaultIfEmpty()
join user in _dbContext.Users on
usersNeeded equals false &&
account.AccountManager equals user.Id into user_
from user__ in user_.DefaultIfEmpty();
You can make a list with the tables that you need (or you don't need) and add an extra condition on the join clause.
Upvotes: 1