4

Controller が Index ActionResult で返したモデルから結果セットを選択するために、どこかで linq ステートメントを使用する必要がありました。これを行うために、「ビュー レーザーで 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 に答える