当前位置:  开发笔记 > 编程语言 > 正文

C#,Linq2Sql:是否可以将两个可查询连接成一个?

如何解决《C#,Linq2Sql:是否可以将两个可查询连接成一个?》经验,为你挑选了1个好方法。

我有一个可查询的,我已经使用各种WhereWhereBetween语句来缩小收集到一组特定的.现在我需要添加一种Where || WhereBetween.换句话说,我不能像现在一样把它们连在一起,因为它可以作为一个And.那么,我该怎么做呢?

我看到两种可能性:

    从我拥有的一个查询中创建两个查询,一个使用Where,一个使用WhereBetween.然后将它们连接起来.不知道这是否可能?此外,虽然不是在我的特定情况下,你很可能最终会重复...

    以某种方式合并Where表达式和在WhereBetween某种Or中创建的表达式.


首先,如上所述,我不确定是否可能.如果是的话,我不太确定这是一个很好的方法.

第二,我可以看到一个选项,但不完全确定所有的细节.以下是WhereBetween我的另一个问题的方法,我现在使用它并且效果很好:

    public static IQueryable WhereBetween(
        this IQueryable source,
        Expression> selector,
        IEnumerable> ranges)
    {
        var param = Expression.Parameter(typeof(TSource), "x");
        var member = Expression.Invoke(selector, param);
        Expression body = null;
        foreach (var range in ranges)
        {
            var filter = Expression.AndAlso(
                Expression.GreaterThanOrEqual(member,
                     Expression.Constant(range.A, typeof(TValue))),
                Expression.LessThanOrEqual(member,
                     Expression.Constant(range.B, typeof(TValue))));
            body = body == null ? filter : Expression.OrElse(body, filter);
        }
        return body == null ? source : source.Where(
            Expression.Lambda>(body, param));
    }

我想我可以将它的表达式构建部分提取到一个新方法中.也许是这样的:

    public static IQueryable WhereBetween(
        this IQueryable source,
        Expression> selector,
        IEnumerable> ranges)
    {
        return source.Where(WhereBetween(selector, ranges));
    }

    public static Expression> WhereBetween(
        Expression> selector,
        IEnumerable> ranges)
    {
        var param = Expression.Parameter(typeof(TSource), "x");
        var member = Expression.Invoke(selector, param);
        Expression body = null;
        foreach (var range in ranges)
        {
            var filter = Expression.AndAlso(
                Expression.GreaterThanOrEqual(member,
                     Expression.Constant(range.A, typeof(TValue))),
                Expression.LessThanOrEqual(member,
                     Expression.Constant(range.B, typeof(TValue))));
            body = body == null ? filter : Expression.OrElse(body, filter);
        }
        return body == null 
            ? ø => true
            : Expression.Lambda>(body, param);
    }

然后我可以使用该新方法来获取表达式而不是可查询表达式.所以,让我说我有WhereBetween(ø => ø.Id, someRange)和例如ø => ø.SomeValue == null.我如何将这两者与Or结合起来?我正在看方法中Expression.OrElse使用的WhereBetween,我认为这可能是我需要的,或者也许是这个Expression.Or.但是我对这个表达方式非常不稳定,所以我不确定在这里选择什么,或者即使我在正确的轨道上:p

有人可以给我一些指示吗?



1> Marc Gravell..:

这里有两个选项 - Queryable.Union或表达式组合.我一般都喜欢后者,通过OrElse- 你可以用2个表达式(至少使用LINQ-to-SQL)来处理2个表达式(见下文) - 但在任何一种情况下都应该得到组合:

    using(var ctx = new DataClasses1DataContext())
    {
        ctx.Log = Console.Out;
        Expression> lhs =
            x => x.Country == "UK";
        Expression> rhs =
            x => x.ContactName.StartsWith("A");

        var arr1 = ctx.Customers.Where(
            lhs.OrElse(rhs)).ToArray();

        var arr2 = ctx.Customers.Where(lhs)
            .Union(ctx.Customers.Where(rhs)).ToArray();
    }

两者arr1arr2每个只执行1次数据库命中(尽管TSQL不同;第一个ORWHERE子句中有一个;第二个有两个单独的查询UNION).

这是我使用的扩展方法:

static Expression> OrElse(
    this Expression> lhs,
    Expression> rhs)
{
    var row = Expression.Parameter(typeof(T), "row");
    var body = Expression.OrElse(
        Expression.Invoke(lhs, row),
        Expression.Invoke(rhs, row));
    return Expression.Lambda>(body, row);
}

推荐阅读
ifx0448363
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有