在ASP.Net使用的ViewModels和LINQ MVC 4 [英] Using ViewModels and Linq in ASP.Net MVC 4

查看:138
本文介绍了在ASP.Net使用的ViewModels和LINQ MVC 4的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我以期学习MVC来更新一些旧的ASP / ASP.Net Web应用程序我来管理我的雇主 - 和我开始让我周围的ViewModels(以及试图头 - 因此后)。

在我的例子,以帮助我学习 - 我有一个汽车经销店。每个经销商都有一定数量的汽车,他们出租。汽车被列为CarTypes - 每个CarType可以有许多与之相关的汽车的

  CarType.cs//
//保存类型的汽车 - 这有一个与汽车类一对多的关系
//
[表(Af - Ag型)]
公共类CarType
{
    [键]
    公众诠释TYPE_ID {搞定;组; }
    公众诠释dealer_id {搞定;组; }
    公共字符串TYPE_NAME {搞定;组; }
    公共字符串type_desc {搞定;组; }
    公共虚拟的ICollection<汽车>汽车{搞定;组; }
}
Car.cs//
//保存实际的汽车
//[表(TCAR)]
公共类车
{
    [键]
    公众诠释car_id {搞定;组; }
    公众诠释dealer_id {搞定;组; }
    公众诠释TYPE_ID {搞定;组; }
    公众诠释car_order {搞定;组; }
    公共字符串car_name {搞定;组; }
    公共虚拟的ICollection<租赁和GT;出租{搞定;组; }
    公共虚拟CarType CarType {搞定;组; }
}
Rental.cs//
//这个拥有汽车时,被录用的记录,并为它的经销商,多长时间
//[表(能泰)]
公共类服务
{
    [键]
    公众诠释rental_id {搞定;组; }
    公众诠释dealer_id {搞定;组; }
    公众诠释car_id {搞定;组; }
    公众的DateTime hire_from {搞定;组; }
    公众的DateTime hire_to {搞定;组; }
    公共虚拟小汽车{搞定;组; }
}

以上类映射到我的数据库。我读过,使用这样的模式是要避免的,而是你应该使用一个ViewModel。

我想在我的例子做的,就是让人们搜索特定的经销商,与给定的日期,天数聘请他们需要。

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


  1. 日期租车须

  2. 需要汽车天数

  3. 的DealerID(这是从URL取 - 例如。
    http://mycars.com/search/avail/dealerGlasgow

  4. 汽车类型的列表中可用

  5. 可用的每个车型的编号

要做到这一点,我想出了下面的视图模型:

  SearchViewModel.cs公共类SearchViewModel
{
    [需要]
    公众的DateTime从{搞定;组; }
    [需要]
    公众诠释DaysHire {搞定;组; }
    公众诠释dealer_id {搞定;组; }
    公众的IQueryable<汽车>汽车{搞定;组; }
}

现在我用这个视图模型来显示在ASP.Net MVC天搜索表单日历和数量 - 所以我从填充隐藏字段的dealer_id形式(从网址获取),并搜索数据库,用LINQ的下面在我的控制器。

搜索首先查找重叠的人正在寻求聘用日期的任何租金 - 它把这些信息为:

  preBookedCars

然后,它通过dealer_id搜索汽车 - 但不包括任何已经聘请了:

  freeCars

控制器code是:

  //
    // POST:/搜索/效用/ DealerName    [使用AllowAnonymous]
    [HttpPost]
    公众的ActionResult效用(SearchViewModel型号,串号)
    {
        如果(ModelState.IsValid)
        {
            VAR dteFrom = model.From;
            VAR dteTo = model.From.AddDays(model.Days);            //搜索这些日期的任何预订,为specifed经销商            VAR prebookedCars = db.Cars
                。凡(汽车= GT; car.Rentals.Any(租金=>
                    (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)
                ));            //搜索汽车,包括汽车类型(所以我们可以有介绍等),并排除已经聘请了任何汽车            VAR freeCars = db.Cars.Include(CarType)
                。凡(汽车= GT; car.dealer_id == model.dealer_id)
                。除(prebookedCars)
                .OrderBy(O => o.car_order);
            model.Cars = freeCars;            返回查看(模型);
        }
        其他
        {
            返回查看(模型);
        }
    }

我有几个问题:

一)是我的LINQ为prebookedCars效率?有没有一种方法,我应该检查:

  model.dealer_id == rental.dealer_id

...只是一次,而不是3倍(例如,通过具有2凡例如条款)?

二)查询,当我踩着通过VS模式 - 即 - 模型中的每一辆汽车,我可以在VS点击了下来。 model.Cars结果查看] .Rentals - 看到与汽车相关的所有服务 - 尽管我想突出部分要排除的已排的汽车。如果我不使用详细程度在我看来,这很重要,这个名单是在模型中?或一个事实,即它的存在,这是否意味着我增加不必要的开销,我的模型/查询?

三)我真的想结束了,在我看来,能够显示:

CarType(TYPE_NAME)及说明(type_desc) - 在一个下拉框,该类型的汽车提供数

我已经结束得到的是具体的个人汽车 - 而不是能够显示:

model.CarType.type_name和model.CarType.count

我如何改变我的查询,返回汽车类型可用的数量(或者我可以用我的模型上面有做不知何故?)

我知道这是很长篇大论 - 但我想展示的细节,将帮助 - 如果有人能帮助我查询的任何部分,我AP preciate它

谢谢,马克


解决方案

  

一)是我的LINQ为prebookedCars效率?有没有一种方法,我应该是
  检查:


  
  

model.dealer_id == rental.dealer_id ......只有一次,而不是3倍
  (例如,通过具有2个,其中,例如条文)?


您可能会改变你的声明,以先放测试model.dealer_id:

  db.Cars.Where(车= GT; car.Rentals.Any(租金=>
                    (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))
                ));

对于A:有几件事情,可能是错的。您是否使用code首先为这个?如果是这样,你可能需要实现的Equals函数,或者它可能是一个铸造LINQ的事情。 这篇文章可能与

对于C:我真的不知道我理解你的问题 - 但我认为你想计数的可用汽车对于任何给定的汽车类型和显示呢?如果是这样,因为你已经拥有汽车(假设B工作)的枚举为你通过汽车类型的列表进行迭代,你可以从你的previous查询获取可用汽车数量:

 的foreach(在db.CarTypes VAR cartype)
            {
                变种numberAvailable = freeCars.Where(FC = GT; fc.CarType == cartype);
            }

这是一种伪code作为循环应该在你的看法,并很可能会做一些其他的事情,但我希望你的想法。

I'm learning MVC with a view to updating some of the old ASP/ASP.Net web apps I have to manage for my employer - and I'm starting to get my head around ViewModels (well trying - hence the post).

In my example to help me learn - I've got a Car Dealership. Each DealerShip has a number of cars that they hire out. The Cars are classed as CarTypes - and each CarType can have a number of Cars associated with it.

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


}

The above classes map to my database. I've read that using Models like this is to be avoided, and instead you should use a ViewModel.

What I want to do in my example, is allow people to search a particular dealer, with a given date, and number of days hire they require.

I then want to populate the viewmodel with the following:

  1. Date Car Required From
  2. Number of Days Car is required
  3. The DealerID (which is taken from the URL - eg. http://mycars.com/search/avail/dealerGlasgow )
  4. A list of car types available
  5. Number of each car type available

To do this, I came up with the ViewModel below:

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

Now I use this view model to display a Calendar and number of days search form in ASP.Net MVC - so I populate the dealer_id from a hidden field on the form (taken from the URL), and search the database, using the LINQ below in my controller.

The Search first looks for any rentals which overlap the dates the person is looking to hire for - it places that info into:

preBookedCars

It then searches for Cars by the dealer_id - and excludes any that have already been hired:

freeCars

The Controller code is:

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


    }

I've a couple of questions:

a) Is my Linq for prebookedCars efficient? Is there a way I should be checking the:

model.dealer_id == rental.dealer_id

...just once, instead of 3 times (eg. by having 2 Where clauses for example)?

b) The query, when I'm stepping through the model in VS - for each Car in the model, I can click down in VS - ie. model.Cars.[Results View].Rentals - and see every Rental associated with that Car - even although I jut wanted to exclude any Cars which had already been booked. If I don't use that level of detail in my view, does it matter that this list is within the model? Or the fact that it's there, does that mean that I'm adding unnecessary overhead to my model/query?

c) I really wanted to end up, in my View, being able to show:

CarType (type_name) and Description (type_desc) - and in a drop down box, the number of cars of that type available.

What I've ended up with is the specific individual Cars - rather than being able to show:

model.CarType.type_name and model.CarType.count

How could I change my query, to return the number of car types available (or can I do it somehow with the model I have above?)

I know this is very long winded - but I thought showing the detail, would help - if anyone is able to help with any part of my query, I'd appreciate it.

thanks, Mark

解决方案

a) Is my Linq for prebookedCars efficient? Is there a way I should be checking the:

model.dealer_id == rental.dealer_id ...just once, instead of 3 times (eg. by having 2 Where clauses for example)?

You could alter your Statement to put the test for model.dealer_id first:

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

Regarding B: There are a few things that could be wrong. Are you using code first for this? If so, you may need to implement the Equals function, or it might be a casting linq thing. This article may be related

Regarding C: I'm not really sure I understand your question - but I think you're wanting to count the available cars for any given car type and display it? If so, since you already have an enumeration of available cars (assuming b works) as you're iterating through the list of car types you could get the number of available cars from your previous query:

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

This is kind of pseudo-code as the loop should be in your view, and will probably be doing a number of other things, but I hope you get the idea.

这篇关于在ASP.Net使用的ViewModels和LINQ MVC 4的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆