public async Task <PagedResults <Opening> > GetOpeningsAsync( PagingOptions pagingOptions, SortOptions <Opening, OpeningEntity> sortOptions, SearchOptions <Opening, OpeningEntity> searchOptions, CancellationToken ct) { var rooms = await _context.Rooms.ToArrayAsync(); var allOpenings = new List <OpeningEntity>(); foreach (var room in rooms) { // Generate a sequence of raw opening slots var allPossibleOpenings = _dateLogicService.GetAllSlots( DateTimeOffset.UtcNow, _dateLogicService.FurthestPossibleBooking(DateTimeOffset.UtcNow)) .ToArray(); var conflictedSlots = await GetConflictingSlots( room.Id, allPossibleOpenings.First().StartAt, allPossibleOpenings.Last().EndAt, ct); // Remove the slots that have conflicts and project var openings = allPossibleOpenings .Except(conflictedSlots, new BookingRangeComparer()) .Select(slot => new OpeningEntity { RoomId = room.Id, Rate = room.Rate, StartAt = slot.StartAt, EndAt = slot.EndAt }); allOpenings.AddRange(openings); } var pseudoQuery = allOpenings.AsQueryable(); pseudoQuery = searchOptions.Apply(pseudoQuery); pseudoQuery = sortOptions.Apply(pseudoQuery); var size = pseudoQuery.Count(); var items = pseudoQuery .Skip(pagingOptions.Offset.Value) .Take(pagingOptions.Limit.Value) .ProjectTo <Opening>() .ToArray(); return(new PagedResults <Opening> { TotalSize = size, Items = items }); }
public async Task <PagedResults <Opening> > GetOpeningsAsync(PagingOptions paggingOptions) { var rooms = await _context.Rooms.ToArrayAsync(); var allOpenings = new List <Opening>(); foreach (var room in rooms) { // Generate a sequence of raw opening slots var allPossibleOpenings = _dateLogicService.GetAllSlots( DateTimeOffset.UtcNow, _dateLogicService.FurthestPossibleBooking(DateTimeOffset.UtcNow)) .ToArray(); if (allPossibleOpenings.Length == 0) { continue; } var conflictedSlots = await GetConflictingSlots( room.Id, allPossibleOpenings.First().StartAt, allPossibleOpenings.Last().EndAt); // Remove the slots that have conflicts and project var openings = allPossibleOpenings .Except(conflictedSlots, new BookingRangeComparer()) .Select(slot => new OpeningEntity { RoomId = room.Id, Rate = room.Rate, StartAt = slot.StartAt, EndAt = slot.EndAt }) .Select(model => _mapper.Map <Opening>(model)); allOpenings.AddRange(openings); } var paggedOpenings = allOpenings.Skip(paggingOptions.Offset.Value).Take(paggingOptions.Limit.Value); return(new PagedResults <Opening> { Items = paggedOpenings, TotalSize = allOpenings.Count }); }
public async Task <IEnumerable <Opening> > GetOpeningsAsync(CancellationToken ct) { var rooms = await _context.Rooms.ToArrayAsync(); var allOpenings = new List <Opening>(); foreach (var room in rooms) { // Generate a sequence of raw opening slots var allPossibleOpenings = _dateLogicService.GetAllSlots( DateTimeOffset.UtcNow, _dateLogicService.FurthestPossibleBooking(DateTimeOffset.UtcNow)) .ToArray(); var conflictedSlots = await GetConflictingSlots( room.Id, allPossibleOpenings.First().StartAt, allPossibleOpenings.Last().EndAt, ct); // Remove the slots that have conflicts and project var openings = allPossibleOpenings .Except(conflictedSlots, new BookingRangeComparer()) .Select(slot => new OpeningEntity { RoomId = room.Id, Rate = room.Rate, StartAt = slot.StartAt, EndAt = slot.EndAt }) .Select(model => Mapper.Map <Opening>(model)); allOpenings.AddRange(openings); } return(allOpenings); }
/// <summary> /// /// "entity framework translates the linw expression in to sql query, so that it can execuete the whole thing on databse/server , instead of fetching the whole data to client side" /// /// 'new System.Linq.SystemCore_EnumerableDebugView<RestApi.Models.BookingEntity>(k).Items' threw an exception of type 'System.InvalidOperationException' /// /// /// /// The LINQ expression 'DbSet<BookingEntity> /// .LeftJoin( /// outer: DbSet<RoomEntity>, /// inner: b => EF.Property<Nullable<Guid>>(b, "RoomId"), /// outerKeySelector: r => EF.Property<Nullable<Guid>>(r, "Id"), /// innerKeySelector: (o, i) => new TransparentIdentifier<BookingEntity, RoomEntity>( /// Outer = o, /// Inner = i /// )) /// .Where(b => b.Inner.Id == __roomid_0 && ___dateLogicService_1.DoesConflict( /// b: b.Outer, /// start: __start_2, /// end: __end_3))' could not be translated. Either rewrite the query in a form that can be translated, /// or switch to client evaluation explicitly by inserting a call to either AsEnumerable(), AsAsyncEnumerable(), ToList(), or ToListAsync(). /// See https://go.microsoft.com/fwlink/?linkid=2101038 for more information. /// /// The above is failing because it is not supported in .net core 3.0 and above /// /// </summary> /// <param name="roomid"></param> /// <param name="start"></param> /// <param name="end"></param> /// <returns></returns> public async Task <IEnumerable <BookingRange> > GetConflictingSlots( Guid roomid, DateTimeOffset start, DateTimeOffset end) { //https://docs.microsoft.com/en-us/ef/core/querying/client-eval //https://stackoverflow.com/questions/1578778/using-iqueryable-with-linq var result = _context.Bookings.Where(b => (b.Room.Id == roomid)).AsEnumerable().Where(b => _dateLogicService.DoesConflict(b, start, end)).SelectMany(existing => _dateLogicService .GetAllSlots(existing.StartAt, existing.EndAt)); //_dateLogicService.DoesConflict(b, start, end))).Select(x=>x); /*var l = k * * .SelectMany(existing => _dateLogicService * .GetAllSlots(existing.StartAt, existing.EndAt));*/ //.ToArrayAsync(); // return await Task.FromResult(l.ToArray()); return(await Task.FromResult(result.ToArray())); }