是否可以组合这两个linq查询?

时间:2013-08-12 13:07:45

标签: c# asp.net linq

我正在使用实体框架来返回我的数据。

我有两个几乎相同的方法/查询。唯一的区别是,有一个额外的Where声明。

第一个查询获取已接受事务的平均值,第二个查询获取所有事务的平均值。

以下是两种方法:

    static IEnumerable<BuyerEarning> GetBuyerEPA()
    {
        var collectTo = DateTime.Now.AddDays(-1).DayEnd();
        var collectFrom = collectTo.AddDays(-29).DayStart();

        using (var uow = new UnitOfWork(ConnectionString.PaydayLenders))
        {
            var r = new Repository<MatchHistory>(uow.Context);

            return r.Find()
                .Where(x =>
                    x.ResultTypeId == (int)MatchResultType.Accepted &&
                    x.CreatedOn <= collectTo &&
                    x.CreatedOn >= collectFrom)
                .GroupBy(x => new
                {
                    x.BuyerId,
                    x.TreeId,
                    x.TierId
                })
                .ToList()
                .Select(x => new BuyerEarning(
                    x.Key.BuyerId,
                    x.Key.TreeId,
                    x.Key.TierId,
                    x.Average(y => y.Commission)))
                .ToList();
        }
    }

    static IEnumerable<BuyerEarning> GetBuyerEPL()
    {
        var collectTo = DateTime.Now.AddDays(-1).DayEnd();
        var collectFrom = collectTo.AddDays(-29).DayStart();

        using (var uow = new UnitOfWork(ConnectionString.PaydayLenders))
        {
            var r = new Repository<MatchHistory>(uow.Context);

            return r.Find()
                .Where(x =>
                    x.CreatedOn <= collectTo &&
                    x.CreatedOn >= collectFrom)
                .GroupBy(x => new
                {
                    x.BuyerId,
                    x.TreeId,
                    x.TierId
                })
                .ToList()
                .Select(x => new BuyerEarning(
                    x.Key.BuyerId,
                    x.Key.TreeId,
                    x.Key.TierId,
                    x.Average(y => y.Commission)))
                .ToList();
        }
    }

我想使用1返回BuyerId,TreeId,TierId,EpaValue,EplValue,而不是2个不同的查询。这是可能的,如果是的话,怎么样?

4 个答案:

答案 0 :(得分:3)

您可以使用谓词作为参数创建辅助方法:

static IEnumerable<BuyerEarning> GetXXXX(Func<MatchHistory, bool> predicate = null)
{
    var collectTo = DateTime.Now.AddDays(-1).DayEnd();
    var collectFrom = collectTo.AddDays(-29).DayStart();

    using (var uow = new UnitOfWork(ConnectionString.PaydayLenders))
    {
        var r = new Repository<MatchHistory>(uow.Context);

        var filtered = r.Find()
                        .Where(x.CreatedOn <= collectTo && x.CreatedOn >= collectFrom);

        if(predicate != null)
            filtered = filtered.Where(predicate);

        return filtered 
            .GroupBy(x => new
            {
                x.BuyerId,
                x.TreeId,
                x.TierId
            })
            .ToList()
            .Select(x => new BuyerEarning(
                x.Key.BuyerId,
                x.Key.TreeId,
                x.Key.TierId,
                x.Average(y => y.Commission)))
            .ToList();
    }
}

然后在每个原始方法中使用它:

static IEnumerable<BuyerEarning> GetBuyerEPA()
{
    return GetXXXX(x => x.ResultTypeId == (int)MatchResultType.Accepted);
}

static IEnumerable<BuyerEarning> GetBuyerEPL()
{
    return GetXXXX();
}

Btw。 ,为什么在最终投影前使用ToList()?它使Average计算由应用程序执行(使用LINQ to Objects),这比SQL Server完成时效率低得多。

答案 1 :(得分:3)

为什么不重构Where子句并将其作为变量传递?

var epaFilter = new Func<MatchHistory, bool>(x => x.ResultTypeId == (int)MatchResultType.Accepted &&      x.CreatedOn <= collectTo &&                    x.CreatedOn >= collectFrom);
var eplFilter = new Func<MatchHistory, bool>(x => x.CreatedOn <= collectTo && x.CreatedOn >= collectFrom);        

private static IEnumerable<MatchHistory> GetBuyerByFilter(Func<MatchHistory,Boolean> filter)
{
    var collectTo = DateTime.Now.AddDays(-1).DayEnd();
    var collectFrom = collectTo.AddDays(-29).DayStart();

    using (var uow = new UnitOfWork(ConnectionString.PaydayLenders))
    {
        var r = new Repository<MatchHistory>(uow.Context);

        return r.Find()
            .Where(filter)
            .GroupBy(x => new
            {
                x.BuyerId,
                x.TreeId,
                x.TierId
            })
            .ToList()
            .Select(x => new BuyerEarning(
                x.Key.BuyerId,
                x.Key.TreeId,
                x.Key.TierId,
                x.Average(y => y.Commission)))
            .ToList();
    }
}

答案 2 :(得分:3)

虽然大多数其他答案都向您展示了如何使用相同的代码在EPL和EPA之间切换查询,但我相信您所询问的是如何在单个查询中获取这两个值。

static IEnumerable<BuyerEarning> GetBuyerEPA()
{
    var collectTo = DateTime.Now.AddDays(-1).DayEnd();
    var collectFrom = collectTo.AddDays(-29).DayStart();

    using (var uow = new UnitOfWork(ConnectionString.PaydayLenders))
    {
        var r = new Repository<MatchHistory>(uow.Context);

        return r.Find()
            .Where(x =>
                x.CreatedOn <= collectTo &&
                x.CreatedOn >= collectFrom)
            .GroupBy(x => new
            {
                x.BuyerId,
                x.TreeId,
                x.TierId
            })
            .Select(x => new BuyerEarning(
                x.Key.BuyerId,
                x.Key.TreeId,
                x.Key.TierId,
                x.Average(y => y.Commission), //EPL
                x.Where(y => y.ResultTypeId == (int)MatchResultType.Accepted)
                    .Average(y => y.Commission)) //EPA
            .ToList();
    }
}

答案 3 :(得分:2)

好像你想要这个:

static IEnumerable<BuyerEarning> GetBuyer(bool acceptedOnly)
{
    var collectTo = DateTime.Now.AddDays(-1).DayEnd();
    var collectFrom = collectTo.AddDays(-29).DayStart();

    using (var uow = new UnitOfWork(ConnectionString.PaydayLenders))
    {
        var r = new Repository<MatchHistory>(uow.Context);
        IQueryable<MatchHistory> results = r.Find()
            .Where(x =>
                x.CreatedOn <= collectTo &&
                x.CreatedOn >= collectFrom);

        if (acceptedOnly)
        {
            results = results
                .Where(x => x.ResultTypeId == (int)MatchResultType.Accepted);
        }

        return results
            .GroupBy(x => new
            {
                x.BuyerId,
                x.TreeId,
                x.TierId
            })
            .ToList()
            .Select(x => new BuyerEarning(
                x.Key.BuyerId,
                x.Key.TreeId,
                x.Key.TierId,
                x.Average(y => y.Commission)))
            .ToList();
    }
}