【问题标题】:How do I create a list from stored procedure results Entity Framework如何从存储过程结果实体框架创建列表
【发布时间】:2018-12-18 20:38:42
【问题描述】:

我正在使用 ASP.NET MVC 和 EF 创建一个车辆预订应用程序,用户可以在该应用程序中在一个日期时间预订多辆车辆,如果他们愿意的话。我创建了一个存储过程来防止重复预订车辆,但在弄清楚如何将结果添加到列表中时遇到了麻烦。

示例:我想为 2018 年 12 月 18 日的 12:00 到 13:00 保留 Vehicle#1 和 Vehicle#2....存储过程转到 db 以发现 Vehicle#1 已经从12:00 至 13:00,但未预留车辆#2。由于运行了foreachalreadyReservedVehicle 返回了.Count() = 0 的结果,因为它看到了最后一个结果,即 Vehicle#2 未被保留。它应该会显示一条错误消息,指出不允许重复预订,因为车辆#1 已被预订,但它不计算该预订。

有没有办法收集这两个结果并告诉应用程序因为这 2 辆车中的一辆被预订,所以这两辆车都不能被预订?

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");
        }
    }
}

以上是我到目前为止所拥有的,并且我知道我已经接近了,因为假设用户只尝试预订一辆已经预订的车辆,我所拥有的将起作用。当他们尝试为多辆车创建预订时,代码仅计算列表中的最后一辆车,并将其用作确定是否保存预订的结果。

我考虑将条件语句移到 foreach 中,但我不希望为每个选定的车辆保存预订...这没有任何意义,因为只有 1 个预订要保存,它只有多辆可以与之关联的车辆。

这是查找预留车辆的存储过程:

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)

那么我怎样才能让alreadyReservedVehicle List 将每个结果添加到列表中,以便我可以确定List 是否实际上有一个为0 的Count

更新:

这是存储过程的模型

public partial class usp_PreventDoubleBooking_Result
{
    public int ID { get; set; }
    public DateTime StartDate { get; set; }
    public DateTime EndDate { get; set; }
}

【问题讨论】:

  • 您需要在 foreach 中执行条件语句,以便处理该调用的结果。但是您的测试应该针对.Count() &gt; 0,然后重定向。推迟数据库更新,直到您成功确定没有车辆为这些时间预留。
  • @madreflection 这正是我一直在寻找的东西,现在看起来很容易,因为我把它放好了。谢谢你的指导。 :)
  • 我会把它作为后代的答案。

标签: c# asp.net-mvc stored-procedures


【解决方案1】:
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();
    }
}

【讨论】:

  • 感谢那里的 cmets,这很有帮助! :) 这是拼图的最后一块,我很高兴在年底之前把它从我的盘子里拿出来!告别糟糕的 SharePoint 服务器,迎接新的 Web 应用程序!哈哈
  • 恭喜你。
【解决方案2】:

你可以这样做:

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

您必须创建一个与存储过程匹配的模型。

【讨论】:

  • 我的错,我应该在帖子中包含模型,我编辑帖子以显示usp_PreventDoubleBooking存储过程的模型。
  • 我需要为此解决方案创建一个新方法吗?我收到一条错误消息:await can only be used within an async method, consider marking the method with async and changing its return type to Task
  • @Jamie 不请自来的建议:改用ToList。转换为异步代码可能是一个兔子洞,因为你还没有使用它,它可能会让你脱轨。看看这个答案是否适用于ToList,然后探索异步代码。
  • 感谢@madreflection,但我仍然不确定我应该在代码的哪个位置使用该语句。我也不确定context 是什么。上面的代码真的与我已经拥有的(下面)不同吗? alreadyReservedVehicle = db.usp_PreventDoubleBooking(selectedVehicle.ID, reservation.StartDate, reservation.EndDate).ToList();
  • 我也不是。我很难理解您的流程,但我希望 3xGuy 的回答会在异步问题消除后有所帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多