【问题标题】:Creating an IQueryable to Equal int32?创建一个等于 int32 的 IQueryable?
【发布时间】:2014-10-08 13:35:53
【问题描述】:

我正在尝试创建一个查询扩展,它将一个可为空的 int sql 列值与一个值进行比较。但我已经挣扎了 8 个多小时才能找到任何可行的解决方案。

我已经在这方面找到了很多帮助。但是所有的言论都没有帮助我。

我已多次更改代码,但似乎没有任何效果。我想创建类似于 WHERE ManagerID IN (10,20,30) 的东西

主要代码

IQueryable<Users> query = _context.CreateObjectSet<Users>();
query = query.IsMember(a => a.ManagerID, new Int32?[] { 10,20,30 });
return query.ToList();

当前在执行 query.ToList();它返回给我一个

无法创建“System.Object”类型的常量值。此上下文仅支持原始类型或枚举类型。

public static IQueryable<T> IsMember<T>(this IQueryable<T> source, Expression<Func<T, Int32?>> stringProperty, params Int32?[] searchTerms)
    {
        if (searchTerms == null || !searchTerms.Any())
        {
            return source;
        }

        Expression orExpression = null;
        foreach (var searchTerm in searchTerms)
        {
            var searchTermExpression = Expression.Constant(searchTerm, typeof(object)); // <<--- This cast would make it no longer a primitive type

            var containsExpression = Expression.Call(stringProperty.Body, typeof(Int32?).GetMethod("Equals"), searchTermExpression);

            orExpression = BuildOrExpression(orExpression, containsExpression);
        }

        var completeExpression = Expression.Lambda<Func<T, bool>>(orExpression, stringProperty.Parameters);
        return source.Where(completeExpression);
    }

    private static Expression BuildOrExpression(Expression existingExpression, Expression expressionToAdd)
    {
        return existingExpression == null ? expressionToAdd : Expression.OrElse(existingExpression, expressionToAdd);
    }

标记为常量提供另一种数据类型的行确实导致了问题,但如果我不将其设为对象类型,则表达式将不起作用,因为它无法匹配 Int32?数据类型。

谁能帮帮我?

谢谢

==============================================

附加信息

确实是有一个更大的画面。 我只是想创造一些更动态的东西,也可以用于其他项目。

我想使用一些看起来比所有这些多行更有吸引力的功能

query = query.Like(a => a.UserName, filter.UserName, true);
query = query.Equals(a => a.UserTown, filter.UserTown, true);
query = query.IsMember(a => a.Division, filter.Division); // is an array of possible divisions

它适用于基于字符串的 Like 和 Equals。但希望对(可为空的)整数有类似的产品

我受到以下帖子的启发。它创建了一个搜索功能(我为我的项目重命名为 Like) link

我想创建其他类似的。最后一个布尔值是验证列中是否允许为空。

还使用扩展名的原因是我的过滤器页面中也有很多过滤器。 有了这个扩展,我可以轻松地检查我的 Like 和 Equal 函数的开头是否给出了过滤器,而无需检查我的过滤器是否具有 20x 的值。

public static IQueryable<T> Like<T>(this IQueryable<T> source, Expression<Func<T, string>> stringProperty, string searchTerm, bool isnullValueAllowed)
        if (String.IsNullOrEmpty(searchTerm))
        {
            return query;
        }

【问题讨论】:

  • 为什么不直接使用query.Where(a =&gt; (new Int32?[] { 10,20,30 }).Contains(a.ManagerID) 呢? ..只是问

标签: c# entity-framework iqueryable


【解决方案1】:

不清楚为什么要创建此扩展,因为您可以简单地编写如下内容:

query.Where(user => (new[]{10,20,30}).Contains(user.ManagerId)).ToList();

但是,假设实际用例比您给出的示例稍微复杂一些,您能否将表达式构造为与常量 Int32 的比较或与 null 的比较,具体取决于 searchTerm.HasValue() 是否为真?

【讨论】:

    【解决方案2】:

    您需要在这里使用相等运算符== 而不是Equals 方法。它实际上使您的表达式代码更简单:

    foreach (var searchTerm in searchTerms)
    {
        var comparison = Expression.Equals(stringProperty.Body, 
            Expression.Constant(searchTerm));
    
        orExpression = BuildOrExpression(orExpression, comparison);
    }
    

    当然,正如其他人所提到的,您不需要构建一个表示每个比较的 OR 的表达式,您只需在 lambda 中的集合上使用 Conatains,查询提供程序就可以了这一切都给你。

    【讨论】:

    • 我找到了 Int32?没有嵌入 Equal 函数。是否可以创建一个与 string.Equal 类似的扩展?
    • @Cedric 当然会。
    猜你喜欢
    • 1970-01-01
    • 2011-02-11
    • 1970-01-01
    • 2023-01-05
    • 2020-10-16
    • 2015-03-28
    • 1970-01-01
    • 1970-01-01
    • 2011-05-31
    相关资源
    最近更新 更多