某处我不得不使用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语句放在这个循环中。 我该怎么办?
答案 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
。没关系,因为它不是业务逻辑,它是一个正确的查看操作(将数据排入表中,让我们说)。