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();