【问题标题】:linq-to-entity dynamic querieslinq 到实体的动态查询
【发布时间】:2014-04-28 06:39:06
【问题描述】:

我目前正在将旧系统迁移到 .Net,但遇到了这个问题。 我想返回结果,但我仍然需要在函数之后对其进行细化,但是使用此代码,我别无选择,只能从数据库中调用结果并过滤内存中的结果,这样性能很差。

public IQueryable<User> GetUser(string[] accessCodes)
{
    string condition = "";
    if (accessCodes == null)
    {
         condition = " AccessCode IS NOT NULL "
    }
    else
    {
        for (int i = 0; i <= accessCodes.Length - 1; i++)
        {
            condition += " AccessCode LIKE '%" + accessCodes[i].ToString() + "%' ";
            if (i + 1 <= code.Length - 1)
            {
                condition += " OR ";
            }
        }
    }

    return context.ExecuteQuery<User>("SELECT * FROM User WHERE " + condition, null).ToList();
}

我已经尝试过这种方法,但我被卡住了:

public IQueryable<User> GetUser(string[] accessCodes)
{
    IQueryable<User> basequery = from u in context.User 
                                 select u;

    if (accessCodes == null)
    {
         basequery = basequery.Where(n => n.AccessCode != null);
    }
    else
    {
        for (int i = 0; i <= accessCodes.Length - 1; i++)
        {
            // what am I supposed to do here?
        }
    }

    return basequery;
}

我希望有不需要第三方库的解决方案。

【问题讨论】:

  • 您能否简单地解释一下您要达到的目标?您想根据什么条件过滤用户?

标签: c# linq linq-to-entities


【解决方案1】:

你可以试试Any:

else
{
    output = output.Where(u => accessCodes.Any(a => u.AccessCode.Contains(a)));
}

或者你可以使用PredicateBuilder:

if (accessCodes == null)
{
    output = output.Where(u => u.AccessCode == null);
}
else
{
    var predicate = PredicateBuilder.False<User>();

    for (int i = 0; i <= accessCodes.Length - 1; i++)
    {
        predicate = predicate.Or(u => u.AccessCode.Contains(accessCodes[i]))
    }

    output = output.Where(predicate);
}

我还更改了您的if 部分:Where 方法不会修改源,它返回新的查询定义,因此您必须将其分配回output 才能使其工作。

【讨论】:

  • 嗨,Marcin,当我使用“.Any”时,它会抛出异常“DbExpressionBinding 需要一个带有集合 ResultType 的输入表达式。”。我试过直接使用谓词生成器,它也抛出错误“不支持 LINQ 表达式节点类型'Invoke'”。我已经阅读了 PredicateBuilder 指令,为了在实体框架中使用 PredicateBuilder,我需要使用“LINQKit.dll”。不使用 LINQKit.dll 是否有任何解决方法?
  • 您好,没关系,.Any() 就足够了,看来我一直在使用 char[] 而不是 string[] 导致异常。
【解决方案2】:

这应该适合你:

IQueryable<User> basequery = from u in context.User 
                             select u;
if (accessCodes == null)
{
    basequery = basequery.Where(u => u.AccessCode != null);
}
else
{
    basequery = basequery.Where(u => accessCodes.Contains(u=>u.AccessCode));
}

还要确保您返回 basequery,因为您的方法中的 output 未定义且未使用。

【讨论】:

  • 如果只有一个访问代码,这将起作用,但正如我在上面发布的那样,有时它需要多个访问代码,这就是它在循环中的原因。
  • accessCodes.Contains(u=>u.AccessCode) 它会产生你需要的东西。 Contains 遍历代码并 linq 正确处理。使用 ToTraceString() 方法检查输出查询。
  • .Contains 是不够的,假设 accessCode 仅由字符串“m”组成,它必须检索“m”、“mx”、“m3”、“mp”而不是“m” ' 仅限。
  • 抱歉,我想搜索列表中的访问代码。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多