简体   繁体   中英

How do I create a list from stored procedure results Entity Framework

I am using ASP.NET MVC and EF to create a vehicle reservation app in which a user will be able to reserve multiple vehicles for one datetime, if they want. I created a stored procedure to prevent double booking of vehicles, but am having trouble figuring out how to add the results to a list.

Example: I want to reserve Vehicle#1 and Vehicle#2 for 12/18/2018 from 12:00 to 13:00....stored procedure goes to db to find out that Vehicle#1 is already reserved from 12:00 to 13:00, but Vehicle#2 is not reserved. Due to the foreach that runs, alreadyReservedVehicle comes back with the result of .Count() = 0 because it sees the last result, which is that Vehicle#2 is not reserved. It should be showing an error message to say double booking is not allowed, since Vehicle#1 is already reserved, but it isn't counting that reservation.

Is there a way to collect both results and tell the application that because one of those 2 vehicles are reserved, that neither vehicle can be reserved?

public ActionResult Create([Bind(Include = "ID,StartDate,EndDate,RequestorID,Destination,PurposeOfTrip,TransportStudentsFG,LastChangedBy,LastChangedDate,VehicleList,ThemeColor")] Reservations reservation)
{
    if (ModelState.IsValid)
    {
        var selectedVehicles = reservation.VehicleList.Where(x => x.IsChecked == true).ToList();
        List<usp_PreventDoubleBooking_Result> alreadyReservedVehicle = null;

        // get each vehicle that was selected to be reserved then check db to make sure it is available
        foreach (var selectedVehicle in selectedVehicles) 
        {             
            using (VehicleReservationEntities db = new VehicleReservationEntities())
            {
                alreadyReservedVehicle = db.usp_PreventDoubleBooking(selectedVehicle.ID, reservation.StartDate, reservation.EndDate).ToList();                             
            }
        }

        if (alreadyReservedVehicle.Count() == 0) // create a new reservation if the vehicle is available at the selected date and time
        {
            db.Reservations.Add(reservation);
            reservation.LastChangedDate = DateTime.Now;
            db.SaveChanges();
        }
        else
        {
            //return error message on page if vehicle is already reserved
            TempData["Error"] = "Double booking of vehicles is not allowed. Please choose another vehicle/time. Check the availability timeline before reserving to ensure there are no errors. Thank you.";
            return RedirectToAction("Create");
        }
    }
}

Above is what I have so far and I know I am close, because what I have will work assuming a user is only trying to reserve one vehicle that is already booked. It's when they are trying to create a reservation for multiple vehicles where the code only counts the last vehicle in the list and uses that as the result that determines whether or not the reservation will be saved.

I thought about moving the conditional statement into the foreach, but I don't want the reservation to be saved for each vehicle that was selected...that wouldn't make any sense because there is only 1 reservation to be saved, it just has multiple vehicles that can be associated to it.

Here is the stored procedure that finds the reserved vehicles:

SELECT 
    v.ID, r.StartDate, r.EndDate 
FROM 
    dbo.Reservations r
JOIN 
    dbo.ReservationToVehicle rtv ON r.id = rtv.ReservationID
JOIN 
    dbo.Vehicles v ON v.ID = rtv.VehicleID
WHERE
    (v.ID = @VehicleID)
    AND (r.StartDate <= @NewEndDate) 
    AND (r.EndDate >= @NewStartDate)

So how can I get the alreadyReservedVehicle List to add each result to the list so I can determine if the List actually has a Count of 0?

UPDATE:

Here is the model for the stored procedure

public partial class usp_PreventDoubleBooking_Result
{
    public int ID { get; set; }
    public DateTime StartDate { get; set; }
    public DateTime EndDate { get; set; }
}
public ActionResult Create(/*Bind attribute omitted*/ Reservations reservation)
{
    if (ModelState.IsValid)
    {
        // Is 'IsChecked' nullable? If not, "== true" is redundant.
        var selectedVehicles = reservation.VehicleList.Where(x => x.IsChecked == true).ToList();

        // get each vehicle that was selected to be reserved then check db to make sure it is available
        using (VehicleReservationEntities db = new VehicleReservationEntities())
        {
            foreach (var selectedVehicle in selectedVehicles)
            {
                // 'alreadyReservedVehicle' can be declared here because you don't need to let it
                // out of its cage, I mean the loop.
                List<usp_PreventDoubleBooking_Result> alreadyReservedVehicle =
                    db.usp_PreventDoubleBooking(selectedVehicle.ID, reservation.StartDate, reservation.EndDate).ToList();

                if (alreadyReservedVehicle.Count() > 0)
                {
                    //return error message on page if vehicle is already reserved
                    TempData["Error"] = "Double booking of vehicles is not allowed. Please choose another vehicle/time. Check the availability timeline before reserving to ensure there are no errors. Thank you.";
                    return RedirectToAction("Create");
                }
            }
        }

        // create a new reservation if the vehicle is available at the selected date and time
        db.Reservations.Add(reservation);
        reservation.LastChangedDate = DateTime.Now;
        db.SaveChanges();
    }
}

You could do something like:

var preventDoubleBookingList= await context.Database.SqlQuery<usp_PreventDoubleBooking>("sproc_name", prams_here).ToListAsync();

You will have to create a model that matches the sproc.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM