0

我有以下代码

[WebGet]
        public Bid GetHighestBidInOpenAuctions(int auctionEventId)
        {
            var auctionEvent = CurrentDataSource.AuctionEvents.Where(x => x.Id == auctionEventId).FirstOrDefault();
            var auctionIds = CurrentDataSource.Auctions.Where(x => x.AuctionEventId == auctionEventId && x.Ends > DateTime.UtcNow).Select(x => x.Id).ToList();

            var bids = CurrentDataSource.Bids.Where(x => auctionIds.Any(t => t == x.AuctionId));

            // If the auction Event has not yet started or there are no bids then show auction with high pre-sale estimate.
            if (bids.Count() == 0 || auctionEvent.Starts > DateTime.UtcNow)
            {
                return null;
            }

            var highestBid = bids.Where(b => b.IsAutobid == false).OrderByDescending(b => b.Amount).FirstOrDefault();

            return highestBid;
        }

此行引发以下异常

if (bids.Count() == 0 || auctionEvent.Starts > DateTime.UtcNow)

Some part of your SQL statement is nested too deeply. Rewrite the query or break it up into smaller queries.

怎么了?

编辑

我试过这样做

IQueryable<Bid> bids = CurrentDataSource.Bids.Where(b => 0 == 1);
            foreach(var auctionId in auctionIds)
            {
                int id = auctionId;
                bids = bids.Union(CurrentDataSource.Bids.Where(b => b.AuctionId == id));
            }

但我仍然得到同样的错误。

4

3 回答 3

1

不要使用子查询,而是尝试将出价查询替换为:

var bids = CurrentDataSource.Bids.Where(b => b.AuctionEventId == auctionEventId
                && b.Auction.AuctionEvent.Starts > DateTime.UtcNow
                && b.Auction.Ends > DateTime.UtcNow);

if (bids.Count() == 0
{
    return null;
}
于 2012-11-18T17:29:04.800 回答
0

似乎当您的数据库中有太多东西时,您会收到此错误(在我的情况下为 auctionIds),因为生成的 sql 嵌套太深。为了解决这个问题,我想出了这个解决方案。如果有人可以做得更好,那就去做。我发布这个是因为将来有人可能会遇到这个错误,如果他们这样做,在没有更好的解决方案的情况下,这可能会对他们有所帮助。

 [WebGet]
        public Bid GetHighestBidInOpenAuctions(int auctionEventId)
        {
            /* 
             * This method contains a hack that was put in under tight time constraints.  The query to
             * get bids for all open auctions used to fail when we had a large number of open auctions.
             * In this implementation we have fixed this by splitting the open auctions into groups of 20
             * and running the query on those 20 auctions and then combining the results.
            */

            const int auctionIdSegmentSize = 20;
            var auctionEvent = CurrentDataSource.AuctionEvents.Where(x => x.Id == auctionEventId).FirstOrDefault();
            var auctionIds = CurrentDataSource.Auctions.Where(x => x.AuctionEventId == auctionEventId && x.Ends > DateTime.UtcNow).Select(x => x.Id).ToList();

            int numberOfSegments = auctionIds.Count/auctionIdSegmentSize;
            if (auctionIds.Count % auctionIdSegmentSize != 0)
                numberOfSegments++;

            var bidsList = new List<IQueryable<Bid>>();
            for (int i = 0; i < numberOfSegments; i++)
            {
                int start = i*auctionIdSegmentSize;
                int end;
                if (i == numberOfSegments - 1)
                {
                    end = auctionIds.Count - 1;
                }
                else
                {
                    end = ((i + 1)*auctionIdSegmentSize) - 1;
                }

                var subList = auctionIds.GetRange(start, (end - start) + 1);
                bidsList.Add(CurrentDataSource.Bids.Where(b => subList.Any(id => id == b.AuctionId)));
            }

            // If the auction Event has not yet started or there are no bids then show auction with high pre-sale estimate.
            if (IsBidsCountZero(bidsList) || auctionEvent.Starts > DateTime.UtcNow)
            {
                return null;
            }

            var highestBid = FindHighestBid(bidsList);

            return highestBid;
        }

        private Bid FindHighestBid(List<IQueryable<Bid>> bidsList)
        {
            var bids = new List<Bid>();
            foreach (var list in bidsList)
            {
                bids.Add(list.Where(b => b.IsAutobid == false).OrderByDescending(b => b.Amount).FirstOrDefault());
            }

            bids.RemoveAll(b => b == null);

            if (bids.Count == 0)
                return null;

            bids.Sort(BidComparison);

            return bids[0];
        }

        private int BidComparison(Bid bid1, Bid bid2)
        {
            if (bid1.Amount < bid2.Amount)
                return 1;
            if (bid1.Amount > bid2.Amount)
                return -1;
            return 0;
        }

        private bool IsBidsCountZero(List<IQueryable<Bid>> bidsList)
        {
            int count = 0;
            foreach (var list in bidsList)
            {
                count += list.Count();
            }

            return count == 0;
        }
于 2012-11-18T20:25:24.010 回答
0

问题在于auctionIds.Any(t => t == x.AuctionId)EF 无法创建正确的查询。您可以将其更改为:

var bids = CurrentDataSource.Bids.Where(x => auctionIds.Contains(x.AuctionId));

EF可以将auctionIds转换为集合并传递给DB。

于 2017-03-16T06:32:49.650 回答