我正在学习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。
在我的例子中,我想做的是允许人们搜索特定的经销商,并指定日期和他们需要的雇佣天数。
然后我想用以下内容填充视图模型:
- 车辆需求起始日期
- 需要车辆的天数
- DealerID(取自URL,例如。http://mycars.com/search/avail/dealerGlasgow)
- 可用车型列表
- 每种可用车型的数量
为了做到这一点,我提出了下面的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);
}
在您看来,这是一种伪代码,因为循环应该是这样的,并且可能会做许多其他事情,但我希望您能理解。