简体   繁体   English

根据Select&Where子句动态加入Linq

[英]Dynamic joins in Linq according to the Select & Where Clause

I have a list on my UI for which the user can customize the columns to be displayed. 我的UI上有一个列表,用户可以为其自定义要显示的列。 The data for this list is being fetch from a Linq query with 10 joins which is considerably expensive. 该列表的数据是从具有10个连接的Linq查询中获取的,这非常昂贵。 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. 我正在使用Entity Framework Core2。我想看看是否有一种方法可以根据用户选择显示在列表上的特定列集或已应用的过滤条件,将联接动态添加到查询中。客户端上的列表。

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 这是我的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 例如,如果我要将参数发送到我的API,例如...&Select="Code,City" ,则将排除对地址和用户的联接

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: Linq将是这样的:

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. 您可以使用所需(或不需要)的表列出列表,并在join子句上添加额外条件。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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