C# 根据Select&;Where子句

C# 根据Select&;Where子句,c#,linq,api,C#,Linq,Api,我的UI上有一个列表,用户可以自定义要显示的列。此列表的数据是从具有10个联接的Linq查询中获取的,这相当昂贵。我使用的是实体框架核心2。 我想看看是否有一种方法可以根据用户选择显示在列表上的特定列集或应用于客户端列表的筛选,动态地将连接添加到查询中 例如,以以下查询为例: SELECT a.Id, a.Code, a.Sector, ad.City, ad.Country, u.FullName FROM Accounts a INNER JOIN Addresses ad on ad.Ac

我的UI上有一个列表,用户可以自定义要显示的列。此列表的数据是从具有10个联接的Linq查询中获取的,这相当昂贵。我使用的是实体框架核心2。 我想看看是否有一种方法可以根据用户选择显示在列表上的特定列集或应用于客户端列表的筛选,动态地将连接添加到查询中

例如,以以下查询为例:

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'
这是我的林肯

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();
}
public IEnumerable Get(querycause querycause,out-ForGetCollectionOptions-ForGetCollectionOptions)
{
使用(_dbContext)
{
var结果=(
来自_dbContext.Accounts中的帐户
将account.ID上的_dbContext.Addresses中的地址与address.account连接到address中_
来自地址中的地址。DefaultIfEmpty()
将用户加入_dbContext.Users on account.AccountManager等于user.Id_
来自user_uuu.DefaultIfEmpty()中的user_uuu
选择新帐户
{
Id=account.Id,
代码=account.Code.Trim(),
扇区=帐户.Sector.Trim(),
城市=地址城市,
国家=地址\国家,
AccountManager=用户\全名
}
);
//过滤
ApplyFilterClause(参考结果,查询原因FilterClause);
}
返回result.toList();
}
如果用户选择只查看每个帐户的列代码和扇区,我就不需要包括地址或用户的连接

如果用户选择只查看code列、sector列和基于国家/地区的过滤器,则我只需要包含到地址的联接,而不需要包含到users表的联接

有没有一种通用的方法可以实现这个逻辑?
例如,如果我要将参数发送到我的API,例如
…&Select=“code,City”
,我将排除与地址和用户的连接,如果连接的性能不好,您只需确保在不需要表的信息时条件为false即可

例如,如果您不需要用户信息,可以执行以下操作:

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'
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();
Linq将是这样的:

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'
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();

您可以列出所需(或不需要)的表,并在join子句中添加额外条件。

..&Select=“代码,城市-是的,您需要使用OData协议,我不想使用OData。我的API使用entityFramework.Core2@MaciejLos那篇文章中的解决方案被描述为在性能方面无效,这就是我放弃它的原因。是的,你可以按照你的要求去做,但你需要检查被查询的内容,并将其推到所需的路径,以得到你想要的内容,他们需要指定列,然后我会问为什么,您不能使用延迟加载得到类似的结果。感觉你把事情复杂化了。请注意,您的示例是内部连接,代码是外部连接。PS连接没有那么贵。。。假设它们被正确过滤!没有过滤器,是的,它不会预成型。显示ApplyFilterClause的代码,以确保您以可识别的方式执行此操作。另外,你的使用语句看起来很奇怪,也许没关系,只是说它看起来很奇怪。不过我很喜欢你的名字,我可能会继续使用这种风格。我认为你需要使用“usersNeeded equals true”来达到问题中的要求。这样它就不会与Users表连接。