具有SelectList的ViewModel和具有单个reocrd的LINQ查询结果

时间:2016-10-24 19:56:04

标签: c# asp.net-mvc linq asp.net-mvc-viewmodel

我们如何使用以下两个属性填充ViewModel:

  1. 来自LINQ查询的query result type仅返回单个记录
  2. SelectList类型
  3. 换句话说,假设我们有一个视图,根据所选ID只显示一部电影。我们希望从下拉列表中为该电影分配一年的发布时间,如何填写以下ViewModel和Controller中的????

    注意:在以下ViewModel中,如果我使用类型为IQueryable<Movie>的myMovie属性,并将ViewModel的此属性分配给来自跟随控制器的查询qrySingleMovie,则会收到错误the name qrySingleMovie does not exist in the current context

    模型

    public class Movie
    {
        public int ID { get; set; }
        public string Title { get; set; }
        public DateTime ReleaseDate { get; set; }
        public string Genre { get; set; }
        public decimal Price { get; set; }
    }
    
    public class Year
    {
      public int YearId {get; set;}
      public int MovieYear {get; set;}
    }
    

    视图模型

    public class MovieGenreViewModel
    {
        public ???? myMovie;
        public SelectList MovieReleaseYears;
        public int ReleasedYr { get; set; }
    }
    

    控制器

    public async Task<IActionResult> Index(int MovieID)
    {
        // Use LINQ to get list of Release years.
        IQueryable<string> YearQuery = from m in _context.Years
                                        orderby m.MovieYear
                                        select m.MovieYear;
    
        //Following query selects only a single movie based on Primary Key ID
        var qrysingleMovie = from m in _context.Movies
                     where m.ID == movieID
                     select m;
    
        var movieReleaseYrVM = new MovieGenreViewModel();
        movieReleaseYrVM.MovieReleaseYears = new SelectList(await YearQuery.ToListAsync());
        movieReleaseYrVM.myMovie = ????
    
        return View(movieReleaseYrVM);
    }
    

    更新

    在我的真实项目中,模型具有许多属性,相应的视图也会显示大部分属性。我在想是否有一种更简单的方法来定义一个不包含模型所有属性的ViewModel,例如ASP.NET Article定义了一个视图模型MovieGenreViewModel但是他们在他们的视图中使用了List他们正在迭代多部电影。我试图模仿他们的例子但在我的情况下,它是一个SelectList的单个记录(不是记录列表)。如何使用单个记录模拟这种情况,并且无法在View Model中包含大量模型属性?

2 个答案:

答案 0 :(得分:1)

由于您想要更新电影记录,获取电影记录所需的只是它的唯一ID。那么为什么不将MovieId属性添加到视图模型中呢?如果您希望在UI中显示MovieName,也可以添加MovieName属性。

请记住视图模型特定于视图。创建视图模型时,无需模拟整个实体模型。只添加您的视图绝对需要的属性。

public class MovieGenreViewModel
{
    public int MovieId;
    public string MovieName { set;get;}
    public SelectList MovieReleaseYears;
    public int ReleasedYr { get; set; }
}

现在,在您的GET操作中设置这些属性值。

public async Task<IActionResult> Index(int MovieID)
{
    var vm = new MovieGenreViewModel();

    var movie =  _context.Movies.FirstOrDefault(x=>x.ID==movieID);

    if(movie==null)
       return Content("Movie not found"); // to do :Return a view with "not found" message

    IQueryable<string> YearQuery = from m in _context.Years
                                    orderby m.MovieYear
                                    select m.MovieYear;   

    // set the property values. 
    vm .MovieReleaseYears = new SelectList(await YearQuery.ToListAsync());
    vm .MovieId= movie.ID;
    vm .MovieName= movie.Name;

    return View(vm );
}

现在在您的视图中,您将影片ID保存在隐藏字段中,这样当您提交表单时,它将被提交给处理表单提交的HttpPost操作方法。

@model MovieGenreViewModel
@using(Html.BeginForm("AssignYear","Home"))
{
    <p>@Model.MovieName</p>
    @Html.HiddenFor(s=>s.MovieId)
    @Html.DropDownListFor(d=>d.ReleasedYr, Model.MovieReleaseYears)
    <input type="submit"/>
}

您可以使用与AssignYear操作方法参数

相同的视图模型
[HttpPost]
public ActionResult AssignYear(MovieGenreViewModel model)
{
  // check model.MovieId and model.ReleasedYr
  // to do : Save data and return something
}

如果您不希望仅将视图所需的属性添加到视图模型,但希望显示电影的大量属性,则可以考虑向您的类型添加Movie类型的新属性查看模型

public class MovieGenreViewModel
{
    public Movie Movie { set;get;}
    public SelectList MovieReleaseYears;
    public int ReleasedYr { get; set; }
}

您现有的LINQ语句返回一个元素的集合。您无法将电影集合分配给Movie类型的属性。您可以使用FirstOrDefault()方法获取单个对象。

var movie =  _context.Movies.FirstOrDefault(x=>x.ID==movieID);
 //After null check
vm.Movie = movie;

答案 1 :(得分:0)

为什么不能将Movie用作“myMovie”属性的类型? 然后,您可以使用该对象显示example.ie movie.Name 的名称。 您还可以将movieId存储在隐藏字段中,这样当您回发时,它将可供您在服务器端使用。 您可以使用LINQ从数据库中检索该对象,如下所示:

var qrysingleMovie = _context.Movies.Single(m=> m.ID == movieID);

或者,您可以使用2个属性而不是整个对象。一个用于标题,即:字符串MovieName,另一个用于id int MovieId

public string MovieName  { get; set; }
public int MovieId  { get; set; }

注意:请记住,使用“Single”意味着您需要在数据库中放置电影,否则会引发异常。