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

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

问题描述

我正在学习MVC,以便更新我为我的雇主管理的一些旧的ASP / ASP.Net网络应用程序 - 而且我开始关注ViewModels(很好,因此这个帖子)



在我帮助我学习的例子中,我有一个汽车经销商。每个DealerShip都有一些他们租用的汽车。汽车被归类为CarTypes - 并且每个CarType可以有一些与之相关联的汽车。

  CarType.cs 

//
//持有车型 - 这与Car类有一对多的关系
//
[Table(tType)]
public class CarType
{
[Key]
public int type_id {get;组; }
public int dealer_id {get;组; }
public string type_name {get;组; }
public string type_desc {get;组; }
public virtual ICollection< Car>车{get;组; }
}


Car.cs

//
//持有实际的汽车
//

[表(tCar)]
public class Car
{
[Key]
public int car_id {get;组; }
public int dealer_id {get;组; }
public int type_id {get;组; }
public int car_order {get;组; }
public string car_name {get;组; }
public virtual ICollection< Rental>租组; }
public virtual CarType CarType {get;组; }
}


Rental.cs

//
//这是保存汽车何时被雇用的记录,哪个经销商,以及多长时间
//

[Table(tRental)]
public class Rental
{
[Key]
public int rental_id {get;组; }
public int dealer_id {get;组; }
public int car_id {get;组; }
public DateTime hire_from {get;组; }
public DateTime hire_to {get;组; }
public virtual Car Car {get;组; }


}

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



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



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



  1. 需要车数

  2. DealerID(从URL获取 - 例如
    http://mycars.com/search/avail/dealerGlasgow

  3. 汽车列表可用的类型

  4. 可用的每种车型数量

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

  SearchViewModel.cs 

public class SearchViewModel
{
[必需]
public DateTime From {get;组; }
[必需]
public int DaysHire {get;组; }
public int dealer_id {get;组; }
public IQueryable< Car>汽车组; }
}

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



搜索首先查找与该人正在寻找的日期重叠的任何租赁 - 将该信息放入:

  preBookedCars 

然后它通过dealer_id搜索Cars,并排除已经被雇用的任何:

  freeCars 

控制器代码是:

  // 
// POST:/ Search / Avail / DealerName

[AllowAnonymous]
[HttpPost]
public ActionResult可用性(SearchViewModel模型,字符串ID)
{
if(ModelState.IsValid)
{
var dteFrom = model.From;
var dteTo = model.From.AddDays(model.Days);

//搜索这些日期的任何预订,经销商指定

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

//搜索汽车,包括汽车类型(所以我们可以有描述等),并排除任何已经被雇用的汽车

var freeCars = db.Cars .clude(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中逐步浏览模型时,对于模型中的每个Car,我可以在VS中点击下一个 - 即。 model.Cars。[Results View]。Rentals - 并查看与该车相关的每个租赁 - 尽管我想要排除已经预订的任何汽车。如果我不认为这个级别的细节,这个列表在模型中是否重要?或者事实上它在那里,这是否意味着我在我的模型/查询中增加了不必要的开销?



c)我真的想要结束在我的视图,可以显示:



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



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



model.CarType .type_name和model.CarType.count



如何更改我的查询,以返回可用的车型数量(或者我可以以某种方式使用我拥有的型号以上?)



我知道这是很长的时间 - 但我认为显示细节会有所帮助 - 如果任何人能够帮助我查询的任何部分,我谢谢,Mark

解决方案


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 => 

||
(dteTo>(
(dteFrom> = rental.check_in&& dteFrom< rental.check_out) ; rent.check_in&& dteTo< = rental.check_out)
||
(dteFrom< = rental.check_in&& dteTo> = rental.check_out))
));

关于B:有几件事可能是错误的。您是否为此首先使用代码?如果是这样,你可能需要实现Equals函数,或者它可能是一个转换linq的东西。 本文可能相关


$ b $关于C:我不是很确定我明白你的问题 - 但是我想你想计算任何给定的车型可用的汽车,并显示它?如果是这样,由于您已经列出了可用的汽车(假设b工程),因为您正在遍历汽车类型列表,您可以从之前的查询中获取可用汽车的数量:

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

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


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 MVC中使用ViewModels和Linq 4的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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