Using ViewModels and Linq in ASP.Net MVC 4



我正在学习MVC,以更新我必须为雇主管理的一些旧的ASP/ASP.Net web应用程序,我开始了解ViewModels(尝试得很好,因此发布了这篇文章)。

在我的例子中,帮助我学习-我有一个汽车经销商。每艘DealerShip都有自己出租的多辆汽车。汽车被归类为汽车类型,每种汽车类型都可以有多辆汽车与之相关。

CarType.cs
//
// Holds types of car - this has a one to many relationship with Car class
//
[Table("tType")]
public class CarType
{
    [Key]
    public int type_id { get; set; }
    public int dealer_id { get; set; }
    public string type_name { get; set; }
    public string type_desc { get; set; }
    public virtual ICollection<Car> Car { get; set; }
}  

Car.cs
//
// Holds actual Cars
//
[Table("tCar")]
public class Car
{
    [Key]
    public int car_id { get; set; }
    public int dealer_id { get; set; }
    public int type_id { get; set; }
    public int car_order { get; set; }
    public string car_name { get; set; }
    public virtual ICollection<Rental> Rentals { get; set; }
    public virtual CarType CarType { get; set; }
}

Rental.cs
//
// This holds records of when cars are hired, and for which dealer, and for how long
//
[Table("tRental")]
public class Rental
{
    [Key]
    public int rental_id { get; set; }
    public int dealer_id { get; set; }
    public int car_id { get; set; }
    public DateTime hire_from { get; set; }
    public DateTime hire_to { get; set; }
    public virtual Car Car { get; set; }

}

上面的类映射到我的数据库。我读到过避免使用这样的模型,而应该使用ViewModel。

在我的例子中,我想做的是允许人们搜索特定的经销商,并指定日期和他们需要的雇佣天数。

然后我想用以下内容填充视图模型:

  1. 车辆需求起始日期
  2. 需要车辆的天数
  3. DealerID(取自URL,例如。http://mycars.com/search/avail/dealerGlasgow)
  4. 可用车型列表
  5. 每种可用车型的数量

为了做到这一点,我提出了下面的ViewModel:

SearchViewModel.cs
public class SearchViewModel
{
    [Required]
    public DateTime From { get; set; }
    [Required]
    public int DaysHire { get; set; }
    public int dealer_id { get; set; }
    public IQueryable<Car> Cars { get; set; }
}

现在,我使用这个视图模型在ASP.Net MVC中显示日历和天数搜索表单,因此我从表单上的隐藏字段(取自URL)填充dealer_id,并在控制器中使用下面的LINQ搜索数据库。

"搜索"首先查找与此人想要租用的日期重叠的任何租赁,并将这些信息放入:

preBookedCars

然后,它通过经销商id搜索汽车,并排除任何已经雇佣的汽车:

freeCars

控制器代码为:

    //
    // POST: /Search/Avail/DealerName
    [AllowAnonymous]
    [HttpPost]
    public ActionResult Avail(SearchViewModel model, string id)
    {
        if (ModelState.IsValid)
        {
            var dteFrom = model.From;
            var dteTo = model.From.AddDays(model.Days);
            // Search for any bookings for those dates, for the dealer specifed
            var prebookedCars = db.Cars
                .Where(car => car.Rentals.Any(rental =>
                    (model.dealer_id == rental.dealer_id && dteFrom >= rental.check_in && dteFrom < rental.check_out)
                    ||
                    (model.dealer_id == rental.dealer_id && dteTo > rental.check_in && dteTo <= rental.check_out)
                    ||
                    (model.dealer_id == rental.dealer_id && dteFrom <= rental.check_in && dteTo >= rental.check_out)
                ));
            // Search for Cars, include the Car Type (so we can have description etc), and exclude any cars that have already been hired
            var freeCars = db.Cars.Include("CarType")
                .Where(car => car.dealer_id == model.dealer_id)
                .Except(prebookedCars)
                .OrderBy(o => o.car_order);

            model.Cars = freeCars;
            return View(model);
        }
        else
        {
            return View(model);
        }

    }

我有几个问题:

a) 我的预预订汽车Linq有效吗?有没有一种方法我应该检查:

model.dealer_id == rental.dealer_id

只是一次,而不是三次(例如,通过使用2个Where子句)?

b) 查询时,当我在VS中遍历模型时,对于模型中的每辆车,我可以在VS中单击。汽车。[结果视图]。租金-并查看与该车相关的每一次租金-尽管我只是想排除任何已经预订的汽车。如果我在视图中不使用那个级别的详细信息,那么这个列表在模型中有关系吗?或者它在那里,这是否意味着我在给我的模型/查询添加不必要的开销?

c) 在我看来,我真的很想最终能够展示:

CarType(type_name)和Description(type_desc),并在下拉框中显示该类型的可用汽车数量。

我最终得到的是具体的个人汽车,而不是能够显示:

model.CarType.type_name和model。车载类型计数

我如何更改我的查询,以返回可用的汽车类型的数量(或者我可以用上面的型号来做吗?)

我知道这很冗长,但我认为展示细节会有所帮助,如果有人能帮助我解决问题的任何部分,我将不胜感激。

谢谢,Mark

a) 我的预预订汽车Linq有效吗?有没有办法让我检查:

model.dealer_id==rental.dealer_id…仅一次,而不是3次(例如,有2个Where子句)?

你可以修改你的声明,先测试model.dealer_id:

db.Cars.Where(car => car.Rentals.Any(rental =>
                    (model.dealer_id == rental.dealer_id) && (
                    (dteFrom >= rental.check_in && dteFrom < rental.check_out)
                    ||
                    (dteTo > rental.check_in && dteTo <= rental.check_out)
                    ||
                    (dteFrom <= rental.check_in && dteTo >= rental.check_out))
                ));

关于B:有一些事情可能是错误的。您是否首先使用代码?如果是这样,您可能需要实现Equals函数,或者它可能是一个强制转换linq。这篇文章可能与有关

关于C:我真的不确定我是否理解你的问题,但我认为你想统计任何给定车型的可用汽车并显示它?如果是这样的话,当你迭代汽车类型列表时,由于你已经有了可用汽车的枚举(假设b有效),你可以从之前的查询中获得可用汽车的数量:

 foreach (var cartype in db.CarTypes)
            {
                var numberAvailable = freeCars.Where(fc => fc.CarType == cartype);
            }

在您看来,这是一种伪代码,因为循环应该是这样的,并且可能会做许多其他事情,但我希望您能理解。

最新更新