【发布时间】:2017-03-30 16:01:53
【问题描述】:
我正在使用 EF 编写一个 ASP.NET MVC 应用程序。我对我的方法是否合理有一些疑问。 注意:我为这个问题简化了我的基本结构,实际上一切都更松散地耦合。
让我们假设一个视图允许用户更改复杂域模型的属性。数据来自数据库(通过 EF),最后必须重新写回。
据我了解,每个请求都会调用一个新的控制器实例。因此,我使用here as Option 2 描述的“Dispose Pattern”,它确保每个请求都有一个新的 DbContext:
public class MyController : Controller
{
private MyContext repo = new MyContext();
protected override void Dispose(bool disposing)
{
this.repo.Dispose();
base.Dispose(disposing);
}
//more code...
}
现在控制器上有一个public ActionResult Edit(elementId) 方法,它将从数据库中获取一个元素并为其显示一个编辑器。此请求完成后,对 Dbcontext 的任何引用都将消失,但我仍然可以访问从数据库中获取的实体对象,因为 我将它存储在我的会话中。
稍后用户按下视图上的“保存”按钮。对我的 Controller 的 Save 方法的请求再次创建了一个新的 Controller 实例,因此创建了一个新的 DbContext。检索存储在我的会话中的实体对象,并根据用户的输入修改其属性。要将新状态保存到数据库中,我必须将其附加到新上下文中:
public void Save()
{
this.repo.MyTable.Attach(myEntity);
myEntity.Name = "New Name";
this.repo.SaveChanges();
}
这只能在具有myEntity 原始 DbContext 的旧控制器被释放后才能工作,否则“附加”将失败(无法将实体附加到两个上下文)。 我担心我是否可以依赖在此处处理的旧 DbContext。
另外:我知道使用 IoC 框架是一种替代方案。这将如何适用于我的情况,有什么好处?
【问题讨论】:
-
您的link 会列出来。不确定将获取的实体存储在会话中是什么意思 - 无需将其传递给您的视图。最好使用ViewModels。
-
最好保持 DbContext 实例的打开时间尽可能短,仅在确实需要时实例化 DbContext 对象,并在不再需要为特定请求与数据库交互时立即关闭它.从架构的角度来看,我建议您将 IoC 与将处理您的 Web 请求的服务层一起应用,从而使您的控制器“无脂肪”。
-
尝试探索 Unity.Mvc5。这是一个非常易于使用的 IoC 容器,并且最适合 MVC。它为每个请求提供对象生命周期管理,非常适合您的要求。如果您使用它,您将不必担心处理 DbContext。
-
每个人都有自己的; DI 容器通常是非常个人的选择。但是,我不知道 Unity 是 MVC 支持的 最佳 容器的说法是否有很多依据。 Ninject非常与 MVC、Web Api 等配合得很好,使用起来同样简单。
-
@Steve Greene:我可能需要澄清“将实体存储在会话中”的含义。我将我的 ViewModel 存储在会话中,该会话还知道我正在处理的数据库实体的 ID 以及其他一些数据。视图模型会根据用户输入进行相应更改。除了将它存储在会话中之外,我还必须在请求到达控制器时获取对我的 ViewModel 的引用(例如最终调用的 Save-Method 以及在用户与视图交互期间调用的其他一些方法)。跨度>
标签: c# asp.net asp.net-mvc entity-framework