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

データベースにあまりにも多くのものがあると、生成されたSQLが深くネストされすぎるため、このエラー(私の場合はauctionIds)が発生するようです。これを解決するために、私はこの解決策を思いつきました。誰かがもっと上手にできるなら、そうしてください。誰かが将来このエラーに遭遇する可能性があるため、これを投稿しています。

 [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 に答える