在web请求中创建单个
ObjectContext
并不罕见。我在我的Web应用程序中也这样做。但是,在我看来,页面不应该知道
ObjectContext
的存在。
既然您已经在讨论将上下文注入服务的构造函数中,请查看依赖注入(如果您尚未使用)。当您使用依赖注入容器时,可以让容器为您创建该服务并将对象上下文注入该容器。您的页面唯一需要做的就是从容器中请求该服务(理想情况下,您甚至可以让该服务被注入到该页面的构造函数中,但这在Web表单中不可能)。
您的页面将如下所示:
public class MyPage : Page
{
private readonly IMyService service;
public MyPage()
{
this.service = Global.GetInstance<IMyService>();
}
protected void Btn1_OnClick(object s, EventArgs e)
{
this.service.DoYourThing(this.TextBox1.Text);
}
}
在您的应用程序启动路径(Global.asax)中,您可以像这样配置依赖注入框架:
private static Container Container;
public static T GetInstance<T>() where T : class
{
return container.GetInstance<T>();
}
void Application_Start(object sender, EventArgs e)
{
var container = new Container();
string connectionString = ConfigurationManager
.ConnectionStrings["MyCon"].ConnectionString;
container.RegisterPerWebRequest<MyContext>(() =>
new MyContext(connectionString));
container.Register<IMyService, MyRealService>();
Container = container;
}
在这些示例中,我使用了
Simple Injector依赖注入容器,但任何DI容器都可以。
RegisterPerWebRequest
不是核心库的一部分,但
可用作(NuGet)扩展包。该包确保在Web请求结束时处理您的
ObjectContext
。
起初可能会感到复杂,但这样网页就无需担心创建和处理
ObjectContext
的任何细节。
此外,将执行用例的逻辑放置在单个类中:命令。让命令(或系统)确保该操作的原子性。不要让页面负责此事,并且不要在请求结束时进行提交,因为此时您甚至不知道是否可以调用提交。不,让命令自己处理这个问题。这里有
关于编写业务命令的文章。
这个建议同样适用于ASP.NET MVC,尽管您不应该在控制器的构造函数中调用
Global.GetInstance<IMyService>()
,而只需使用构造函数注入(因为MVC对此有很好的支持),并使用
MVC3 Integration package。
还可以查看
此Stackoverflow问题,其中讨论了选择
IObjectContextFactory
或每个请求使用
ObjectContext
之间的区别。
IDbContextFactory
,并让处理程序自己处理上下文的释放,但这导致了一种模式,即我必须从方法到方法,从类到类传递上下文,以便在同一上下文中运行所有内容,这变成了一个维护噩梦。 - Steven