如何将多个LINQ与对象请求组合成单个请求

时间:2015-08-08 12:40:50

标签: c# linq linq-to-objects

我想将GetCurrentAuction重写为单个LINQ请求:

private AuctionInfo GetCurrentAuction()
    {
        var auctions = Auctions.List().ToList();
        var liveAuction = auctions
            .Where(AuctionIsLive)
            .OrderBy(a => a.StartDate)
            .FirstOrDefault();

        if (liveAuction != null)
        {
            return liveAuction;
        }

        var openAuction = auctions
            .Where(AuctionIsOpen)
            .OrderBy(a => a.StartDate)
            .FirstOrDefault();

        if (openAuction != null)
        {
            return openAuction;
        }

        // next upcoming auction
        return auctions
            .Where(a => a.StartDate >= DateTime.UtcNow)
            .OrderBy(a => a.StartDate)
            .FirstOrDefault();
    }

    private bool AuctionIsLive(AuctionInfo auction)
    {
        // WorkflowStage is int
        return auction.WorkflowStage == LIVE_WORKFLOW_STAGE;
    }

    private bool AuctionIsOpen(AuctionInfo auction)
    {
        return auction.WorkflowStage == OPEN_WORKFLOW_STAGE;
    }

有人可以建议如何实现这一目标吗?看起来使用auctions.GroupBy(a => a.WorkflowStage)并不能让我更接近解决方案。

3 个答案:

答案 0 :(得分:3)

您可以通过订购来表示偏好 - 例如:

return
  Auctions.List().ToList()  //--> ToList() not needed here?
  .Where
  ( a =>
    AuctionIsLive(a) ||
    AuctionIsOpen(a) ||
    a.StartDate >= DateTime.UtcNow
  )
  .OrderBy
  ( a => 
    AuctionIsLive( a ) ? 0 :
    AuctionIsOpen( a ) ? 1 : 2
  )
  .ThenBy( a => a.StartDate )
  .FirstOrDefaut();

答案 1 :(得分:2)

你可以使用非常有用吗?? (https://msdn.microsoft.com/en-us/library/ms173224.aspx)运算符并且给出了这个:

        var result = auctions.Where(AuctionIsLive).OrderBy( x => x.StartDate).FirstOrDefault() ?? 
            auctions.Where(AuctionIsOpen).OrderBy( x => x.StartDate).FirstOrDefault() ??
            auctions.Where(a => a.StartDate >= DateTime.UtcNow).OrderBy(a => a.StartDate).FirstOrDefault();

        return result;

答案 2 :(得分:2)

这取决于您正在使用的数据源和LINQ提供程序。 例如,如果您使用LINQ to SQL,那么执行它的方法就是使用Expressions来保存您的内存并最终得到类似于@ fankyCatz的答案:

return Auctions.Where(a => a.WorkflowStage == LIVE_WORKFLOW_STAGE).OrderBy(x => x.StartDate).FirstOrDefault() ??
        Auctions.Where(a => a.WorkflowStage == OPEN_WORKFLOW_STAGE).OrderBy(x => x.StartDate).FirstOrDefault() ??
        Auctions.Where(a => a.StartDate >= DateTime.UtcNow).OrderBy(a => a.StartDate).FirstOrDefault();

然而,仅使用LINQ to Objects我最终得到的答案类似于@ Clay的一个,只是通过映射提高可读性:

public static Dictionary<int, Func<AuctionInfo, bool>> Presedence = 
            new Dictionary<int, Func<AuctionInfo, bool>>
{
    { 0, a => a.WorkflowStage == LIVE_WORKFLOW_STAGE },
    { 1, a => a.WorkflowStage == OPEN_WORKFLOW_STAGE },
    { 2, a => a.StartDate >= DateTime.UtcNow },
};

//in your GetCurrentAuction()
return Auctions.Where(a => Presedence.Any(p => p.Value(a)))
                .OrderBy(a => Presedence.First(p => p.Value(a)).Key)
                .ThenBy(a => a.StartDate)
                .FirstOrDefault();