我正在使用ASP.NET Web窗体应用程序的实体框架,我想知道我应该如何处理ObjectContext
并且它的生命周期。
例如,我有一个InviteService
类来管理邀请,例如创建和接受邀请。该类本身位于Web项目的另一个项目/命名空间中。
InviteUsers()
方法为用户列表创建Invite
个实体,调用存储库将其保存到数据库,并向每个用户邮寄邀请链接。
当用户点击邀请按钮时,会从Page
调用该方法。
我想知道如何使用ObjectContext
ObjectContext
,将其作为参数传递给InviteService
类的构造函数,然后将其置于Render
方法中。Objectcontext
块创建单独的using
。根据Ladislav的答案,选项一对我来说似乎最好:Entity Framework and Connection Pooling 但是选项3似乎也是有效的,因为据我所知,由于连接池没有建立新的数据库连接。
答案 0 :(得分:6)
每个网络请求创建一个ObjectContext
并不罕见。我在我的网络应用程序中这样做。但是,IMO,页面应该对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;
// Allow the container to resolve your context and
// tell it to create a single instance per request.
container.RegisterPerWebRequest<MyContext>(() =>
new MyContext(connectionString));
// Tell the container to return a new instance of
// MyRealService every time a IMyService is requested.
// When MyContext is a constructor argument, it will
// be injected into MyRealService.
container.Register<IMyService, MyRealService>();
Container = container;
}
在这些示例中,我使用了Simple Injector依赖注入容器,尽管任何DI容器都可以。 RegisterPerWebRequest
不是核心库的一部分,而是is available as (NuGet) extension package。该程序包可确保在Web请求结束时处置ObjectContext
。
这一开始可能看起来很复杂,但这样一来,网页就不必担心创建和部署ObjectContext
的任何细节。
此外,将执行用例的逻辑放在单个类中:命令。让命令(或系统)确保该操作的原子性。不要让页面对此负责,并且不要在请求结束时提交,因为此时您不会知道是否可以调用commit。不,让命令自己处理。这是an article about writing business commands。
这个建议也适用于ASP.NET MVC,虽然你不应该在Controller的构造函数中调用Global.GetInstance<IMyService>()
,但只需使用构造函数注入(因为MVC对此有很大的支持)并使用{{3} }。
另请参阅MVC3 Integration package,其中介绍了在IObjectContextFactory
或每次请求ObjectContext
之间进行选择。
答案 1 :(得分:2)
1是最佳解决方案。 在NHibernate中,world被称为session-per-request。
您可以在BeginRequest中实例化ObjectContext并在EndRequest中刷新/提交它。
1优于3,因为您在请求到达时开始使用ORM(在您的情况下为实体框架)。 然后在整个页面生命周期中向树中添加对象,修改类,删除等等。
仅在EndRequest期间,您只能在一个批次中提交所有更改。
编辑:正如@Steven所说,在提交期间处理异常并不完美。
假设你有一个带有保存按钮的网络表单: