1

別の LINQ 結合ステートメントで既に読み込まれている関連プロパティに対して、モデルが再び DB に移動するのはなぜですか?

背景情報:

最近、ASP.NET MVC3 Linq アプリケーションでいくつかのパフォーマンス プロファイリングを実行しましたが、解決したい不可解な結果が得られました。

これは、db 構造の簡略化されたバージョンです。外部キー関係が設定されます。

テーブル クライアント:

ID|Client Name|Vertical ID|
___________________________
1 |Client1    |2          |
2 |Client2    |5          |
3 |Client3    |           |

テーブル垂直

ID|Vertical Name|
_________________
2 |Life         |
5 |Guilt        |

クライアントのリストを表示すると、クライアント名と垂直方向が表示されます。私のコントローラーはシンプルです:

public ActionResult Index()
    {
        ...
    var model = repository.GetAllClients();
        return View(model);
    }

すべてのクライアントを取得すると、垂直テーブル (および他のいくつか) で結合が実行されます。

 public IEnumerable<client> GetAllClients()
    {
        OperationsMetricsDataContext db = new OperationsMetricsDataContext();
        var clients = from c in db.clients
                      join v in db.verticals on c.vertical equals v into tmp1
                      from v in tmp1.DefaultIfEmpty()
                      join sm in db.cel_sm_staffs on c.sm_id equals sm.cel_sm_id into tmp2
                      from sm in tmp2.DefaultIfEmpty()
                      join cel in db.cel_sm_staffs on c.cel_id equals cel.cel_sm_id into tmp3
                      from cel in tmp3.DefaultIfEmpty()
                      select c;
        return clients;
    }

私のビューでは、部分的なクライアント クラスでこのメソッドを使用してバインドした垂直方向の名前を表示しようとします。

public string getVerticalName()
    {
        return this.vertical == null ? "N/A" : this.vertical.vertical_name;
    }

問題:

@foreach (var item in Model) {
<tr>
    <td>
        @Html.Raw(item.client_name)
    </td>
    <td>
        @Html.Raw(item.getVerticalName())
    </td>

私が発見した問題は、元のモデルで結合を指定したにもかかわらず (モデルがビューに渡される前に垂直プロパティに値が読み込まれていることを確認できました)、 getVerticalName メソッドを使用すると、Linq は自動的にデータベースに再度アクセスして垂​​直をロードし、垂直名にアクセスできるようにします。これは非常に非効率的です。なぜなら、クライアントごとに別々の db 呼び出しを行って、垂直方向の情報を取得するだけだからです。

ここで何が欠けていますか?プロパティが既にバインドされていて、それを取得するためにデータベースにアクセスしないことを LINQ が認識すべきではありませんか、それとも、モデルに情報が既に存在することを LINQ に伝えるために指定する必要があるものはありますか?

4

2 に答える 2

2

MVC でどのように動作するかはわかりませんが、おそらく問題は関連エンティティの遅延読み込みです。LoadOptions を使用して、Linq-2-sql を強制的にロードすることができます。

試す

OperationsMetricsDataContext db = new OperationsMetricsDataContext();

DataLoadOptions dlo = new DataLoadOptions();
dlo.LoadWith<Client>(c => c.Vertical);
db.LoadOptions = dlo;
于 2012-11-06T22:53:12.027 に答える
0

私の第一印象は、クエリを一度だけ実行するには、次のように変更する必要があるということですreturn clients;return clients.ToList();

IQueryableあなたのコードがそうであるように、単にキャスト as を返していると思いますIEnumerable。設計上、 IQueryable は列挙されるたびにサーバーに移動します。

于 2012-11-06T22:38:37.857 に答える