1

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

我有 2 个几乎相同的方法/查询。唯一的区别是一个额外的 Where 语句。

第一个查询获取接受交易的平均值,第二个查询获取所有交易的平均值。

以下是2种方法:

    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();
        }
    }

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

4

4 回答 4

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();
    }
}
于 2013-08-12T13:24:25.110 回答
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();
}

顺便提一句。,为什么ToList()在最终投影之前使用?它使Average计算由应用程序执行(使用 LINQ to Objects),这比 SQL Server 执行的效率低得多。

于 2013-08-12T13:14:14.373 回答
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();
    }
}
于 2013-08-12T13:20:49.727 回答
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();
    }
}
于 2013-08-12T13:13:01.950 回答