Asp.net mvc 延迟加载类未加载-MVC

Asp.net mvc 延迟加载类未加载-MVC,asp.net-mvc,entity-framework,lazy-loading,Asp.net Mvc,Entity Framework,Lazy Loading,我有客户: public class Client { public int ClientID { get; set; } public string ClientName { get; set; } public virtual List<Project> Projects { get; set; } } 客户端控制器具有详细信息获取操作: public ActionResult Details(int id) { Client client =

我有客户:

public class Client
{
    public int ClientID { get; set; }
    public string ClientName { get; set; }
    public virtual List<Project> Projects { 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>
为什么不在回发上加载子类


一旦我解决了这个问题,在客户机类中添加一个实例化List类的构造函数是否是一个好主意,以防我导航到数据库中没有任何记录的客户机?

您为重新加载客户机而添加的行将不起任何作用,因为上下文已经有客户机的本地副本。您可以通过在进行更新之前加载客户机/项目来证明这一点。(类似这样的)


我将不得不研究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);
    }

如果验证失败,将重新附着项目,然后再传递回视图。理论上,这应该是可行的,而不是行动重定向。我也会尝试一下。

原因是,在后MVC中,正在构造实际POCO的实例,而不是从POCO派生的代理类的实例。因此,没有重写的虚拟属性来执行延迟加载

解决方案是通过条目显式加载集合(以替换您的Clients.Find(id)调用):


谢谢,但没用。如果我调试它:在保存之前,它没有项目。保存后,仍然没有项目。在我的强制重新加载(查找)后-仍然没有项目。使用
ICollection
意味着EF可以提供它喜欢的任何类,
List
意味着它必须是一个
List
不会覆盖客户端(ClientName)中的更改,从回发中收到?数据库的初始化位置在哪里?@qujck-在客户端控制器中,您确定您的修改保存在数据库中吗?因为您操作的客户机参数是由模型绑定器根据您的操作签名生成的“模型类”(而不是实体代理类imho)。由于客户端类没有构造函数初始化项目,因此项目会得到默认值:null。@tschmit007是,肯定保存了。事实上,如果我将“Find”行替换为客户机详细信息的“return RedirectToAction”,那么它就可以完美地工作。但是我不希望重定向,因为这样我就必须在querystring中传递一条“更新”消息。为什么我不能返回带有更新模型的视图呢?好吧,似乎条目将对象附加到上下文而不加载它。这就是更新后必须重新加载实体(以启用延迟加载)的原因。经典的方法是在更新之前加载实体。为此,您可以使用或其他方法。这里的另一个选项是使用局部视图,并直接从数据库向该视图传递项目的模型,因此它不是来自更新的模型实例。
client = db.Clients.Find(client.ClientID);
client = db.Clients.Find(client.ClientID);
client.Projects.ToList();
db.Entry(client).State = EntityState.Modified;
db.SaveChanges();
    [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);
    }
db.Entry(client).Collection( c => c.Projects ).Load();