0

当使用下面的方法进行 OR 操作时,我得到了重复的记录。我必须指定一个自定义的 IEqualityComparer 吗?一个简单的 distinct() 不起作用

internal static IQueryable<T> FilterEntity<T>(filters filters, IQueryable<T> entities)
    {
        if (filters.groupOp == "AND")
            foreach (var rule in filters.rules)
                entities = entities.Where<T>(
                    rule.field, rule.data,
                    (WhereOperation)StringEnum.Parse(typeof(WhereOperation), rule.op)
                    );
        else
        {
            //Or
            IQueryable<T> temp = (new List<T>()).AsQueryable();
            foreach (var rule in filters.rules)
            {
                var t = entities.Where<T>(
                    rule.field, rule.data,
                    (WhereOperation)StringEnum.Parse(typeof(WhereOperation), rule.op)
                    );

                    temp = temp.Concat<T>(t).AsQueryable();
            }
            entities = temp;
        }
        return entities;
    }

在下面@usr 的建议后编辑-这给了我在sql profiler 中的正确查询(有一个不同的),但这开始看起来太复杂了-我想要一个更干净的解决方案

    internal static IQueryable<T> FilterEntity<T>(filters filters, IQueryable<T> entities)
    {
        if (filters.groupOp == "AND")
            foreach (var rule in filters.rules)
                entities = entities.Where<T>(
                    rule.field, rule.data,
                    (WhereOperation)StringEnum.Parse(typeof(WhereOperation), rule.op)
                    );
        else
        {
            //Or
            var t1 = entities.Where<T>(filters.rules[0].field,filters.rules[0].data,
                (WhereOperation)StringEnum.Parse(typeof(WhereOperation),filters.rules[0].op)
                );
            for (int i = 1; i<filters.rules.Count(); i++)
            {

                var t = t1.Where<T>(filters.rules[i].field, filters.rules[i].data,
                (WhereOperation)StringEnum.Parse(typeof(WhereOperation), filters.rules[i].op)
                );
              t1.Concat<T>(t).AsQueryable();
            }
           entities  = t1;
        }
        return entities.Distinct<T>();
    }
4

2 回答 2

1

这与Distinct()or无关IEqualityComparer。就是修改后的闭包gotcha,即:循环变量rule必须复制到循环体中:

foreach (var rule in filters.rules)
{
    var rule1 = rule;
    // work with rule1 only.

您可以按照 Usr 的建议执行以下操作:

IQueryable<T> temp = null;
    ....
    foreach (var rule in filters.rules)
    {
        var rule1 = rule;
        var t = entities.Where<T>(rule1.field, rule1.data,
            (WhereOperation)StringEnum.Parse(typeof(WhereOperation), rule1.op));

            if (temp == null)
                temp = t;
            else
                temp = temp.Union(t); // Union!!
    }
}
return temp;

我想知道它是否解决了你的问题。注意Union( 这是一个隐含的Distinct) 的使用。如果它不能解决您的问题,我认为有一些我们看不到的代码(例如在您的 中WhereOperation)会干扰。

于 2012-06-05T08:53:10.967 回答
1

不要以 aList<T>开始查询。从第一个“ t”开始。这样,您将只获得一个在服务器上执行的查询。使用 Union 而不是 Concat 以获得不同的结果。

于 2012-06-05T18:52:29.550 回答