为什么不在View中使用Linq

时间:2013-06-17 16:40:55

标签: asp.net-mvc

某处我不得不使用linq语句从我的Model中选择一个结果集,该控制器在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 个答案:

答案 0 :(得分:7)

在视图本身中使用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命名空间中。根据应用程序的规模,您可能希望将视图模型分解为它们自己的命名空间。我不经常使用{{1}在核心业务对象的实际应用程序中使用命名空间,因此我们的项目结构可能非常不同。这应该可以帮助您,但是您需要确保将问题保持清晰分离。)

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

答案 1 :(得分: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);
}

答案 2 :(得分:1)

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

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

将其移出视图可能无法阻止它,但至少将其置于更明显的位置。

答案 3 :(得分:0)

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

它与Linq本身无关。例如,您可以使用Linq语句来执行OrderBy。没关系,因为它不是业务逻辑,它是一个正确的查看操作(将数据排入表中,让我们说)。