在这个官方ASP.NET MVC Core tutorial中,他们定义了一个ViewModel,如下所示,其中Movie是一个类。然后在Index(...)方法中(在本教程结束时,他们从一个简单的LINQ查询填充ViewModel,如下面的Controller所示:
视图模型:
public class MovieGenreViewModel
{
public List<Movie> movies;
public SelectList genres;
public string movieGenre { get; set; }
}
控制器:
public async Task<IActionResult> Index(string movieGenre, string searchString)
{
// Use LINQ to get list of genres.
IQueryable<string> genreQuery = from m in _context.Movie
orderby m.Genre
select m.Genre;
var movies = from m in _context.Movie
select m;
if (!String.IsNullOrEmpty(searchString))
{
movies = movies.Where(s => s.Title.Contains(searchString));
}
if (!String.IsNullOrEmpty(movieGenre))
{
movies = movies.Where(x => x.Genre == movieGenre);
}
var movieGenreVM = new MovieGenreViewModel();
movieGenreVM.genres = new SelectList(await genreQuery.Distinct().ToListAsync());
movieGenreVM.movies = await movies.ToListAsync();
return View(movieGenreVM);
}
问题:在上面的ViewModel中,属性影片的类型为List<movie>
,而索引(...)方法中使用的查询是一个只涉及一个表的简单查询(电影)。但是如果查询涉及具有两个表的INNER JOIN并因此返回匿名类型的对象,如下所示。在这种情况下,我们如何在ViewModel中声明匿名类型List<.?.>
的列表,然后填充List&lt;。?。&gt;类型的属性。在ViewModel?在下面的示例中,我使用List<dynamic>
或List<object>
定义了一个ViewModel并尝试了myViewModel.list = leftOuterJoinQuery.ToListAsync()
,但错误为Cannot implicitly convert type 'List<<anonymous type: int CategoryId, string CategoryName, string ProdName>>>' to 'System.Collections.Generic.List<dynamic>
:
LINQ INNER JOIN查询:
var innerJoinQuery =
from category in categories
join prod in products on category.ID equals prod.CategoryID
select new { ProductName = prod.Name, Category = category.Name }; //produces flat sequence
更新:
正如下面提到的@StephenMuecke,可以通过创建包含我的查询返回的属性的另一个视图模型来解决问题。但我在想是否有办法避免创建额外的View模型。
答案 0 :(得分:2)
有一种方法可以在不创建新VM的情况下完成它,但我不确定它是否正确。
首先,我将把VM转为以下
public class MovieGenreViewModel
{
public ICollection movies;
public SelectList genres;
public string movieGenre { get; set; }
}
定义辅助方法以从匿名对象组成列表
public static List<T> CreateList<T>(params T[] elements)
{
return new List<T>(elements);
}
最后,更改Index()方法
中的行这
movieGenreVM.movies = await movies.ToListAsync();
到
var output = await innerJoinQuery.ToListAsync();
movieGenreVM.movies = CreateList(output);
希望这有帮助。