通过表达式和第二个对象有条件地过滤IQueryable <t>

时间:2019-05-04 17:02:35

标签: c# entity-framework linq

我不确定标题是否满足我的问题...

但是我想要实现的是在IQueryable上创建自定义扩展方法,其中我的表达式选择类型为AgentEntity的对象,第二个参数为相同类型,但是用于进行条件过滤。

这是我的代码,该代码不起作用,但是提示了我想做什么。

import csv

with open('sort-test.txt', newline='') as f:
    data = [{k: v for k, v in row.items()} for row in csv.DictReader(f, delimiter=':', fieldnames=['name', 'score'], quoting=csv.QUOTE_NONE)]

sorted_data = sorted(data, key = lambda i: i['score'], reverse=True)
for x in sorted_data:
    print (x['name'] + ': ' + x['score'])

用法

public static IQueryable<T> Where<T>(this IQueryable<T> profiles, Func<AgentEntity, AgentEntity> agentSelector, AgentEntity agent)
{
    if (string.IsNullOrEmpty(agent.Mbox))
    {
        return profiles.Where(agentSelector.Mbox == agent.Mbox);
    }

    if (string.IsNullOrEmpty(agent.Mbox_SHA1SUM))
    {
        return profiles.Where(agentSelector.Mbox_SHA1SUM == agent.Mbox_SHA1SUM);
    }

    if (string.IsNullOrEmpty(agent.OpenId))
    {
        return profiles.Where(agentSelector.OpenId == agent.OpenId);
    }

    if (string.IsNullOrEmpty(agent.Account.HomePage))
    {
        return profiles.Where(agentSelector.Account.HomePage == agent.Account.HomePage && agentSelector.Account.Name == agent.Account.Name);
    }

    return profiles;
}

如何将AgentEntity agent = new AgentEntity(){ Mbox = "mailto:lorem@example.com" } _dbContext.OtherEntity.Where(x=> x.Agent, agent); _dbContext.ThirdEntity.Where(x=> x.Object.Agent, agent); 转换为以下表达式agentSelector或其他条件之一,以便在Where子句中用于过滤配置文件。

x=> x.Mbox == agent.Mbox子句期望profiles.Where

谢谢!

1 个答案:

答案 0 :(得分:1)

可以使用IQueryable方法过滤Where。此方法还会返回一个IQueryable,因此,如果您愿意(并且我经常这样做),可以将它们链接在一起以进行多次过滤-我发现这样可以使代码更具可读性,也可以在这些过滤器之间分支代码(为是否过滤条件添加条件)。可能看起来像这样(抱歉,未经测试的代码,但是如果我有错字,欢迎任何修改!):

IQueryable<Foo> foos = _dbContext.Foos;
foos = foos.Where(f => f.Bar == myBar);

if(!string.IsNullOrNothing(myBaz)){
    foos = foos.Where(f => f.Baz == myBaz)
}

因此,在此代码中,Foo个对象的集合在其Bar属性等于myBar时总是被过滤,但是第二个过滤仅在myBar被设置时才应用为空,为空(请注意!使其不为空,这是dotNet的一件事,并且两者都认为您的原始代码中似乎缺少了这些内容)

现在让我尝试将其应用于您要创建的扩展方法。复杂之处在于,从OtherEntityThirdEntityAgentEntity可以得到不同的映射,而我们想使用Func<T, AgentEntity>来定义该映射(请注意,通用类型“ T”的映射)

public static IQueryable<T> Where<T>(this IQueryable<T> profiles, Func<T, AgentEntity> mapping, AgentEntity agent)
{
    if (!string.IsNullOrEmpty(agent.MBox))
    {
        profiles = profiles.Where(p => mapping(p).MBox == agent.MBox);
    }

    return profiles;
}

请注意,我们使用传入的映射功能将每个配置文件转换为用于过滤器的代理。就像您原来的问题一样被调用:

_dbContext.OtherEntity.Where(x=> x.Agent, agent);

还请注意,我要等到函数结束才返回-可能不是您实际要执行的操作-您实际上可能希望在找到一个可以过滤的条件后立即返回! / p>

希望您能走上正确的轨道!