0

Razor で LINQ to Entities を使用しています。私はこのようなものを持っています:

@foreach(Org o in Model) {
    @foreach(User u in o.Users.Where(x => x.Active==true) ) {
       <span> @u.FirstName </span>
    }
}

SQL サーバー プロファイラーを見ると、クエリには 2 つの大きな非効率性があります。

  1. ユーザーテーブルのすべての列を返します
  2. Active==true の行だけでなく、Users テーブルのすべての行を返します。

もちろん問題なく動作しますが、LINQ はこれよりも賢く、より具体的なクエリを SQL サーバーに送信するという印象を受けました。

質問: LINQ で WHERE 句 (Active==true) を渡し、FirstName 列のみを自動的に取得することはできますか?

ps厳密に関連しない限り、ビューのLINQが良い方法であるかどうかにはあまり興味がありません-たとえば、ビューがコンパイルされたコードとは異なる方法で最適化されている場合?

これは私のコントローラコードです:

public ActionResult Index()
{
    xyz_Entities db = new xyz_Entities();
    return PartialView(db.Orgs);
}

更新 - 多くの謝罪、これは実際にはネストされたループであり、重要な場合があります。

4

3 に答える 3

5

ユーザーテーブルのすべての列を返します

確かにそうです-Linqは、データを使用する予定があることを認識していないため、すべての列を返します.

Active==true の行だけでなく、Users テーブルのすべての行を返します。

これは、またはModelを呼び出してコントローラー内のすべてのレコードを具体化するためだと思います。 ToListAsEnumerable

これらを回避するには、ビューではなくコントローラーでクエリを実行し、結果をモデルの一部として、またはViewData辞書に渡します。クエリを次のように切り詰めることができます。

var names = Model.Users.Where(x => x.Active==true)
                       .Select(u => u.FirstName)
                       .ToList();
ViewData["Names"] = names;
于 2013-02-21T14:53:49.610 に答える
2

モデルにデータが入力されている場所は示されていませんが、データ アクセスが行われている場所であり、データベースからすべてのユーザーを取得しているのはそのためです。

このビューに到達するまでに、既にUsersコレクションにデータを設定しているため、メモリ内コレクションで LINQ to Objects を使用しているだけです。

データベース クエリ レベルでフィルターを適用するには、モデルに入力するデータ アクセス コードを変更する必要があります。

于 2013-02-21T14:52:39.340 に答える
1

ToList呼び出しているため、またはToArray宣言された型Model.UsersがのIEnumerable<>代わりにあるため、おそらくすべての行をプルしていますIQueryable<>。拡張メソッドの呼び出しは、通常の静的メソッドのように呼び出されるようにコンパイラーによって書き直され、コンパイラーは宣言された型を使用してIEnumerable<>vsを決定しIQueryable<>ます。

フィルタリングの問題が修正されたら、Select拡張メソッドを使用して、クエリによって返される列を正確にEFに伝えることができます。

于 2013-02-21T14:58:18.787 に答える