private static async Task<Client> _editClient(Client client, ResotelContext ctx) { Client editedClient = await ctx.Clients.FirstOrDefaultAsync(cl => cl.Id == client.Id); // a client only has bookings as reference type properties, and none of them will get changed while we edit the client. // so lets make sur entity knows this foreach(Booking booking in client.Bookings) { Booking trackedBooking = await ctx.Bookings .Include(b => b.Dates) .FirstOrDefaultAsync(b => b.Id == booking.Id); ctx.Entry(trackedBooking).State = EntityState.Unchanged; } // update all non reference properties ctx.Entry(editedClient).State = EntityState.Modified; ctx.Entry(editedClient).CurrentValues.SetValues(client); await ctx.SaveChangesAsync(); return editedClient; }
private static void _removeExistingOptionChoices(IList<OptionChoice> trackedOptionChoices, ResotelContext ctx) { for (int i = trackedOptionChoices.Count - 1; i >= 0; i--) { OptionChoice trackedOptChoice = trackedOptionChoices[i]; ctx.Entry(trackedOptChoice).State = EntityState.Deleted; } }
private static void _updateTrackedOptionDates(DateRange trackedOptDates, DateRange newDateRange, ResotelContext ctx) { ctx.Entry(trackedOptDates).CurrentValues.SetValues(newDateRange); }
private static void _updateTrackedBooking(Booking trackedBooking, Booking booking, ResotelContext ctx) { ctx.Entry(trackedBooking).State = EntityState.Modified; ctx.Entry(trackedBooking).CurrentValues.SetValues(booking); }
/// <summary> /// SaveOrUpdate given Booking /// </summary> /// <param name="booking"></param> /// <returns>The saved booking, with its new id, if a new booking (which was never saved) is passed</returns> public async static Task<Booking> Save(Booking booking) { using (ResotelContext ctx = new ResotelContext()) { Booking savedBooking = null; List<Room> rooms = await _getRoomRequest(ctx, true) .ToListAsync(); List<Option> options = await _getOptionRequest(ctx) .ToListAsync(); Client client = await _getClientRequest(ctx).FirstOrDefaultAsync( cl => cl.Id == booking.Client.Id ); _assignCtxRooms(booking, rooms); _assignCtxOptions(booking, options); if (client != null) { booking.Client = client; } if (booking.Id == 0) { ctx.Entry(booking).State = EntityState.Added; } else { Booking trackedBooking = await ctx.Bookings.FirstOrDefaultAsync(b => b.Id == booking.Id); _updateTrackedBooking(trackedBooking, booking, ctx); await _updateOptionChoices(trackedBooking.OptionChoices, booking.OptionChoices, ctx); await _updateBookingRooms(trackedBooking, booking.Rooms, ctx); await _updateRoomPacks(trackedBooking, trackedBooking.RoomPacks, booking.RoomPacks, ctx); _updateTrackedBookingState(trackedBooking, booking.State, ctx); DateRange trackedBookingDates = await _getTrackedBookingDates(booking.Dates, ctx); trackedBooking.Dates = trackedBookingDates; } List<Room> unavailableRooms = new List<Room>(); using (DbContextTransaction transaction = ctx.Database.BeginTransaction()) { try { await _fillUnavailableRooms(booking, ctx, unavailableRooms); if (unavailableRooms.Count == 0) { savedBooking = await _saveBooking(booking, ctx, transaction); } else { List<Room> unavailableReplacementRooms = await _replaceRooms(booking, ctx, unavailableRooms); if (unavailableReplacementRooms.Count > 0) { HashSet<RoomKind> unreplaceableRoomKinds = new HashSet<RoomKind>(unavailableReplacementRooms.ConvertAll(room => room.Kind)); transaction.Rollback(); throw new InvalidOperationException( $"Impossible de sauvegarder la réservation : nous n'avons plus assez de chambres des types {string.Join(",", unreplaceableRoomKinds)}"); } else { savedBooking = await _saveBooking(booking, ctx, transaction); } } return savedBooking; } catch (Exception) { transaction.Rollback(); throw; } } } }
private static void _updateTrackedOptionChoice(OptionChoice trackedOptChoice, OptionChoice newOptChoice, ResotelContext ctx) { ctx.Entry(trackedOptChoice).CurrentValues.SetValues(newOptChoice); }
private static async Task _updateBookingRooms(Booking trackedBooking, IList<Room> newRooms, ResotelContext ctx) { ctx.Entry(trackedBooking).Collection(b => b.Rooms).EntityEntry.State = EntityState.Modified; trackedBooking.Rooms.Clear(); foreach (Room room in newRooms) { Room trackedRoom = await ctx.Rooms.FirstOrDefaultAsync(r => r.Id == room.Id); trackedBooking.Rooms.Add(trackedRoom); } }
private static void _updateTrackedBookingState(Booking trackedBooking, BookingState newBookingState, ResotelContext ctx) { ctx.Entry(trackedBooking).Property( b => b.State).EntityEntry.State = EntityState.Modified; ctx.Entry(trackedBooking).Property(b => b.State).EntityEntry.CurrentValues.SetValues(newBookingState); }
private static async Task<DateRange> _getTrackedBookingDates(DateRange newBookingDates, ResotelContext ctx) { DateRange trackedBookingDates = await ctx.Set<DateRange>().FirstOrDefaultAsync(dr => dr.Id == newBookingDates.Id); if (trackedBookingDates == null) { trackedBookingDates = ctx.Set<DateRange>().Attach(newBookingDates); } else { // check ctx.Entry(trackedBookingDates).CurrentValues.SetValues(newBookingDates); } return trackedBookingDates; }