3

私はクライアントを持っています:

public class Client
{
    public int ClientID { get; set; }
    public string ClientName { get; set; }
    public virtual List<Project> Projects { get; set; }
}

そしてプロジェクト:

public class Project
{
    public int ProjectID { get; set; }
    public string ProjectName { get; set; }
}

クライアント コントローラーには詳細取得アクションがあります。

public ActionResult Details(int id)
{
    Client client = db.Clients.Find(id);
    return View(client);
}

詳細投稿アクション:

[HttpPost]
public ActionResult Details(Client client)
{
    if (ModelState.IsValid)
    {
        db.Entry(client).State = EntityState.Modified;
        db.SaveChanges();
                    // reload object from db to populate projects property
        client = db.Clients.Find(client.ClientID);
    }
    return View(client);
}

私のクライアントの詳細ビュー:

@model Client
<h1>@Html.DisplayFor(model => model.ClientName)</h1>

@using (Html.BeginForm()) {
    @Html.ValidationSummary(true)
    <fieldset>
        <legend>Client</legend>

        @Html.HiddenFor(model => model.ClientID)

        <div class="editor-label">
            @Html.LabelFor(model => model.ClientName)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.ClientName)
            @Html.ValidationMessageFor(model => model.ClientName)
        </div>

        <p>
            <input type="submit" value="Save" />
        </p>
    </fieldset>
}

<h2>Projects</h2>

<ul>
@foreach (Project project in Model.Projects)
{
    <li>@Html.ActionLink(project.ProjectName, "Details", "Project", new { id = project.ProjectID }, null)</li>
}
</ul>

プロジェクトを持つクライアントに移動すると、正常に動作し、テキスト ボックスにクライアント名とプロジェクトのリストが表示されます。名前を編集して [保存] をクリックします。しかし、サブクラス リストの繰り返しで、「オブジェクト参照がオブジェクトのインスタンスに設定されていません」というビュー エラーが発生します。

データベースからインスタンスをリロードするために、特にこの行を追加しました。これにより、遅延読み込みリスト クラスが再作成され、名前が変更されただけで、get 要求で使用したものと同じインスタンス データが得られると想定されます。

client = db.Clients.Find(client.ClientID);

ポストバックでサブクラスをロードしないのはなぜですか?

これを修正したら、データベースにレコードがない Client に移動する場合に備えて、List クラスをインスタンス化するコンストラクタを Client クラスに追加することをお勧めしますか?

4

3 に答える 3

4

その理由は、ポスト MVC が、POCO から派生したプロキシ クラスのインスタンスではなく、実際のPOCOのインスタンスを構築しているためです。したがって、遅延読み込みを実行するためのオーバーライドされた仮想プロパティはありません。

解決策は、エントリを介して明示的にコレクションをロードすることです (Clients.Find(id) 呼び出しを置き換えるため):

db.Entry(client).Collection( c => c.Projects ).Load();
于 2013-03-26T23:29:46.723 に答える
1

ApplyCurrentValues を調べる必要がありますが、今のところ、これが機能する方法です。

    [HttpPost]
    public ActionResult Details(Client client)
    {
        if (ModelState.IsValid)
        {
            db.Entry(client).State = EntityState.Modified;
            db.SaveChanges();
            return RedirectToAction("Details", new { msg = "saved" });
        }
        client.Projects = db.Clients.Find(client.ClientID).Projects;
        return View(client);
    }

検証が失敗した場合、プロジェクトはビューに戻される前に再接続されます。理論的には、これは Action リダイレクトの代わりに機能するはずです。私もそれを試してみます。

于 2013-03-22T11:45:13.170 に答える
0

コンテキストにはクライアントのローカル コピーが既にあるため、クライアントをリロードするために追加した行は何も実行しません。これは、更新を行う前にクライアント/プロジェクトを熱心にロードすることで証明できます。(このようなもの)

client = db.Clients.Find(client.ClientID);
client.Projects.ToList();
db.Entry(client).State = EntityState.Modified;
db.SaveChanges();
于 2013-03-22T09:17:30.577 に答える