【问题标题】:How to declare List of anonymous type如何声明匿名类型列表
【发布时间】:2016-10-01 02:53:17
【问题描述】:

在这个官方ASP.NET MVC Core tutorial 中,他们定义了一个 ViewModel 如下,其中 Movie 是一个类。然后在 Index(...) 方法中(在本教程的最后,他们从一个简单的 LINQ 查询中填充 ViewModel,如下面的控制器所示:

视图模型:

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 中,movies 属性的类型为 List&lt;movie&gt;,Index(...) 方法中使用的查询是一个仅涉及一个表(电影)的简单查询。但是,如果查询涉及两个表的 INNER JOIN 并因此返回一个匿名类型的对象,如下所示。在这种情况下,我们如何在 ViewModel 中声明一个匿名类型 List&lt;.?.&gt; 的列表,然后在 ViewModel 中填充 List<.> 类型的属性?在下面的示例中,我使用List&lt;dynamic&gt; 或List&lt;object&gt; 定义了一个ViewModel,并尝试了myViewModel.list = leftOuterJoinQuery.ToListAsync(),但得到了Cannot implicitly convert type 'List&lt;&lt;anonymous type: int CategoryId, string CategoryName, string ProdName&gt;&gt;&gt;' to 'System.Collections.Generic.List&lt;dynamic&gt; 的错误:

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 下面建议的那样,可以通过创建另一个包含我的查询返回的属性的视图模型来解决问题。但我在想是否有办法避免创建额外的视图模型。

【问题讨论】:

  • 您需要定义一个包含查询返回的属性的视图模型,并将该查询的结果投影到视图模型的集合中 - select new MyModel { ProductName = prod.Name, .... };
  • @StephenMuecke 是的,这就是我要避免做的事情——那就是创建一个额外的视图模型。我会在上面的帖子中添加一个更新。
  • 您需要编写的代码才能使其与一组匿名对象正常工作,而不仅仅是创建一个简单的视图模型:)(并且您会失去强绑定、智能感知等)
  • @StephenMuecke 嗯!有道理。
  • 您是否有任何理由避免按照@StephenMuecke 的建议创建新模型?您所描述的情况正是它们的用途......为“视图”“建模”数据。

标签: c# asp.net-mvc linq visual-studio-2015


【解决方案1】:

有办法在不创建新虚拟机的情况下完成它,但我不确定它是否正确。

首先,我将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);

希望这会有所帮助。

【讨论】:

  • 感谢您提供替代解决方案。但正如您所认为的和@StephenMuecke 评论的那样,看起来创建一个额外的 VM 比让它在没有额外 VM 的情况下工作更简单。
  • 同意,额外的虚拟机方式很简单。
猜你喜欢
  • 1970-01-01
  • 2018-10-16
  • 1970-01-01
  • 1970-01-01
  • 2015-03-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多