在ASP.Net MVC 4中使用ViewModels和Linq

时间:2012-08-03 14:35:51

标签: asp.net asp.net-mvc asp.net-mvc-3 linq entity-framework

我正在学习MVC,以便更新我必须为我的雇主管理的一些旧的ASP / ASP.Net网络应用程序 - 我开始了解ViewModels(很好的尝试 - 因此帖子)。

在我帮我学习的例子中 - 我有一个汽车经销商。每个DealerShip都有许多他们雇用的汽车。汽车被归类为CarTypes - 每辆CarType都有许多与之相关的汽车。

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。

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

然后我想用以下内容填充viewmodel:

  1. 所需日期车
  2. 需要车辆的天数
  3. DealerID(取自URL - 例如。 http://mycars.com/search/avail/dealerGlasgow
  4. 可用的汽车类型列表
  5. 每种车型的数量
  6. 为此,我想出了下面的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
    

    然后由dealer_id搜索Cars - 并排除任何已经被雇用的人:

    freeCars
    

    Controller代码是:

        //
        // 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 for prebookedCars是否有效?我有办法检查:

    model.dealer_id == rental.dealer_id
    

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

    b)查询,当我在VS中踩过模型时 - 对于模型中的每辆车,我可以在VS中单击 - 即。 model.Cars。[结果视图]。租赁 - 并查看与该车相关的每个租赁 - 即使我只是想要排除任何已经预订的汽车。如果我在视图中没有使用该级别的详细信息,那么此列表是否在模型中是否重要?或者它存在的事实,这是否意味着我在模型/查询中添加了不必要的开销?

    c)我真的想在我的视图中最终能够显示:

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

    我最终得到的是具体的汽车 - 而不是能够展示:

    model.CarType.type_name和model.CarType.count

    我怎样才能更改我的查询,返回可用的车型数量(或者我可以用上面的模型以某种方式进行查询?)

    我知道这是一个很长的啰嗦 - 但我想显示细节,会有所帮助 - 如果有人能够帮助我的查询的任何部分,我会很感激。

    谢谢,Mark

1 个答案:

答案 0 :(得分:2)

  

a)我的Linq for prebookedCars是否有效?我有办法吗?   检查:

     

model.dealer_id == rental.dealer_id ...只需一次,而不是3次   (例如,通过例如2个Where子句)?

您可以更改您的Statement以首先测试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函数,或者它可能是一个强制转换的东西。 This article可能是相关的

关于C:我不确定我理解你的问题 - 但我认为你想要计算任何特定车型的可用车辆并显示它?如果是这样,因为您已经有一个可用汽车的枚举(假设b工作),因为您正在遍历汽车类型列表,您可以从先前的查询中获得可用汽车的数量:

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

这是一种伪代码,因为循环应该在你的视图中,并且可能会做很多其他的事情,但我希望你能得到这个想法。

相关问题