4

在某个地方,我不得不使用 linq 语句从我的模型中选择一个控制器在 Index ActionResult 中返回的结果集。为此,我在 Google 上搜索了“如何在视图剃须刀中使用 linq”,我得到了结果,并且我的应用程序工作正常,但我看到一些建议说“不要在视图中使用 Linq”。为什么我们不应该使用它,但它是可能的?如果我不想使用它,解决方案是什么?

这是我的查询:

 @using System.Linq
 @{var lst = (from x in item.Showtimes select x.ShowtimeDate).Distinct();}
 @foreach (var showTimeItem in lst)
    {
      <option value="@showTimeItem">@showTimeItem</option>   
    }

更新

这是我的控制器索引

public ActionResult Index()
        {
            MelliConcert.Models.MelliConcertEntities db = new  Models.MelliConcertEntities();
            var listOfConcerts = (from x in db.Concert
                                  orderby x.ID ascending
                                  select x).Take(15).ToList();
            return View(listOfConcerts);
        }

我在这样的视图中使用它:

@model IEnumerable<MelliConcert.Models.Concert>
 @foreach (var item in Model)
            {
               @if (item.OpenedForFirst == true)
               { 
                   //... 
               }
               //Some Codes
               @using System.Linq
               @{var lst = (from x in item.Showtimes select x.ShowtimeDate).Distinct();}
               @foreach (var showTimeItem in lst)
               {
                 <option value="@showTimeItem">@showTimeItem</option>   
               }
            }

我的 linq 语句放在这个循环中。我该怎么办?

4

4 回答 4

9

在视图本身中使用 LINQ 本身并没有错。问题不在于您使用的是 LINQ,而在于您正在这样做:

@{var lst = (from x in item.Showtimes select x.ShowtimeDate).Distinct();}

每当您必须在视图中声明和设置变量时,这可能表明您需要修改模型。为此,您的视图模型应该有一个属性。像这样的东西:

public IEnumerable<SomeType> DistinctShowtimes
{
    get
    {
        return (from x in item.Showtimes select x.ShowtimeDate).Distinct();
    }
}

然后,视图中关于 LINQ 的观点变得毫无意义,因为您只需要这样:

@foreach (var showTimeItem in Model.DistinctShowtimes)
{
    <option value="@showTimeItem">@showTimeItem</option>   
}

更新(响应您更新的问题):

现在的问题(虽然稍微少一点)是这样的:

@model IEnumerable<MelliConcert.Models.Concert>

虽然这很好用,但它是有限制的。而你正在经历的就是这种限制。你在问自己,“我如何将不止一件事返回到视图中?” 答案是为该视图创建一个自定义视图模型。现在,您的视图绑定到Concert对象枚举。这很好,如果这就是它所需要的。但事实证明,这并不是它所需要的全部。它有一些需要更多的自定义逻辑。因此,您创建了一个自定义视图模型。像这样的东西:

public class ConcertsViewModel
{
    public IEnumerable<Concert> Concerts { get; set; }
    // other properties, methods, anything
}

然后在您的控制器操作中,您返回其中之一:

public ActionResult Index()
{
    using(var db = new  Models.MelliConcertEntities())
    {
        var concertsModel = new ConcertsModel();
        concertsModel.Concerts = (from x in db.Concert
                                  orderby x.ID ascending
                                  select x).Take(15).ToList();
        return View(concertsModel);
    }
}

(还要注意using语句的使用,在使用资源时应始终使用该语句IDisposable。)

因此,现在您的视图仍在获取Concert对象列表,但它被打包在自定义视图模型中,您可以在其中添加该视图所需的任何更多功能。接下来,在您的视图中,更改模型声明:

@model MelliConcert.Models.ConcertsViewModel

(这假设您将它放在Models命名空间中。根据应用程序的规模,您可能希望将视图模型分解为它们自己的命名空间。我不经常Models在实际应用程序中将命名空间用于核心业务对象,所以我们的项目的结构可能非常不同。这应该可以让您继续前进,但您需要确保将您的关注点完全分开。)

然后在视图代码中,您可以从该对象中引用您需要的内容。因此,如果您需要访问该列表,而不是像@foreach (var item in model)调用@foreach (var item in model.Concerts).

于 2013-06-17T16:45:17.060 回答
2

我认为在这种情况下,参数将是在将模型返回到视图之前对模型进行最大量的处理。

那么为什么不将不同的放映时间返回给视图,然后循环遍历它们呢?

您当前设置的唯一问题是它可能会破坏 MVC 的精神,即分离关注点。视图不应该应用任何需要测试(或尽可能少)的逻辑。通过在模型和控制器中保留逻辑,您可以更轻松地进行单元测试,并且开发人员可以更轻松地阅读视图。

编辑 嘿@ samangholami,您可以使用类将多个对象返回到视图。创建一个名为“PAGENAMEViewModel”或类似名称的类,并为您要返回的每个值创建一个属性。例如:

public class MovieViewModel
{
    public string MovieName { get; set; }
    public IEnumerable<string> Actors { get; set; }
    public IEnumerable<ShowTimeRecord> Showtimes { get; set; }


    public class ShowTimeRecord
    {
        public string TheaterName { get; set; }
        public string TheaterAddress { get; set; }
        public DateTime ShowtimeDate{ get; set; }
    }
}

然后像这样返回您的复杂模型:

public ActionResult Index() 
{
    MovieViewModel model = myMovieHelper.GetMovieData();

    return View(model);
}
于 2013-06-17T16:43:04.880 回答
1

除了可能的关注点分离问题之外,您还可能遇到更难以诊断的性能问题。

如果您的 LINQ 查询以某种方式通过某些 ORM 或类似的方式通过循环结果连接到数据库,您可能会创建 N+1 有问题的场景。

将其移出视图可能不会阻止它,但至少将其放在更明显的地方。

于 2013-06-17T16:52:06.723 回答
0

我认为这是因为它不尊重关注点分离原则,这是 MVC 的基本概念。通过在视图中执行查询,您将获得业务逻辑。

它与 Linq 本身无关。例如,您可以使用 Linq 语句来执行OrderBy. 没关系,因为它不是业务逻辑,而是正确的视图操作(比如说,将数据排序到表中)。

于 2013-06-17T16:47:49.993 回答