在 ASP.NET 中管理实体框架 ObjectContext [英] Managing Entity Framework ObjectContext in ASP.NET

查看:24
本文介绍了在 ASP.NET 中管理实体框架 ObjectContext的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为 ASP.NET Web 窗体应用程序使用实体框架,我想知道应该如何处理 ObjectContext 以及它的生命周期.例如,我有一个 InviteService 类来管理邀请,例如创建和接受邀请.该类本身位于 Web 项目的另一个项目/命名空间中.InviteUsers() 方法为用户列表创建 Invite 实体,调用存储库将它们保存到数据库中,并向每个用户发送邀请链接.

I'm using the Entity Framework for an ASP.NET Web Forms application and I'm wondering how I should deal with ObjectContext and it's lifetime. For example, I have an InviteService class that manages invites such as creating and accepting invites. The class itself is in another project/namespace from the Web project. An InviteUsers() method creates Invite entities for a list of users, calls a repository to save them to the database and mails each user an invite link.

当用户单击邀请按钮时,从 Page 调用该方法.

The method is called from the Page when a user clicks the invite button.

我想知道我应该如何使用 ObjectContext

I would like to know how I should use the ObjectContext

  1. 在每个请求的页面上实例化一个新的 ObjectContext,将其作为参数传递给 InviteService 类的构造函数,然后将其释放到 Render 方法.
  2. 与上述相同,但不是通过构造函数进行设置,而是将其作为参数传递给每个方法.
  3. 在每个方法中使用 using 块创建单独的 Objectcontext.
  1. Instantiate a new ObjectContext on the Page on each Request, passing it as a parameter to the constructor of the InviteService class and then disposing it in the Render method.
  2. Same as above but instead of setting it via the constructor, passing it along as a parameter to each method.
  3. Create a separate Objectcontext in each method with a using block.

根据 Ladislav 在这里的回答,选项一对我来说似乎是最好的:Entity框架和连接池但选项 3 似乎也有效,因为据我所知,由于连接池,没有建立新的数据库连接.

Option one seems best to me based on the answer of Ladislav here: Entity Framework and Connection Pooling But option 3 seems valid as well since as far as I know, no new database connections are made because of connection pooling.

推荐答案

为每个 Web 请求创建单个 ObjectContext 并不罕见.我在我的 Web 应用程序中执行此操作.但是,IMO,页面应该对 ObjectContext 一无所知.

It is not unusual to create a single ObjectContext per web request. I do this in my web applications. However, IMO, the page should know nothing about the ObjectContext.

既然您已经在谈论在服务的构造函数中注入上下文,请看一下依赖注入(如果您还没有使用它).当您使用依赖注入容器时,您可以让容器为您创建该服务并在该容器中注入对象上下文.您的页面唯一要做的就是从容器中请求该服务(理想情况下,您甚至可以将该服务注入该页面的构造函数中,但这对于 Web 表单是不可能的).

Since you are already talking about injecting the context in the constructor of the service, take a look at dependency injection (if you aren't using that already). When you use a dependency injection container, you can let the container create that service for you and inject the object context in that container. The only thing your page has to do is request that service from the container (ideally, you would even let that service be injected in the constructor of that page, but this is not possible with web forms).

您的页面将如下所示:

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)中,您可以像这样配置依赖注入框架:

In the startup path (Global.asax) of your application, you can configure the Dependency Injection framework like this:

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 不是核心库的一部分,但 可用作(NuGet) 扩展包.该包可确保您的 ObjectContext 在 Web 请求结束时被释放.

In these examples I used the Simple Injector dependency injection container, although any DI container will do. The RegisterPerWebRequest is not part of the core library, but is available as (NuGet) extension package. The package ensures that your ObjectContext is disposed when the web request ends.

起初这可能看起来很复杂,但这样网页就不必担心创建和处理 ObjectContext 的任何细节.

This might seem complex at first, but this way the web page doesn't have to worry at all about any details of creating and disposing an ObjectContext.

此外,将执行用例的逻辑放在一个类中:一个命令.让命令(或系统)确保该操作的原子性.不要让页面对此负责,也不要在请求结束时提交,因为那时您将不知道调用 commit 是否可以.不,让命令自己处理.这是一篇关于编写业务命令的文章.

Further, place the logic that executes a use case in a single class: a command. Let the command (or the system) ensure atomicness of that operation. Don't let the page be responsible for this, and don't commit on the end of the request, because at that point you won't know if it is even OK to call commit. No, let the command handle this itself. Here is an article about writing business commands.

这个建议也适用于 ASP.NET MVC,虽然你不应该在 Controller 的构造函数中调用 Global.GetInstance(),而只是使用构造函数注入(因为 MVC 有很好的支持为此)并使用 MVC3 集成包.

This advice holds for ASP.NET MVC as well, although you should not call Global.GetInstance<IMyService>() inside the Controller's constructor, but simply use constructor injection (since MVC has great support for this) and use the MVC3 Integration package.

还请查看这个 Stackoverflow 问题,其中谈到在 IObjectContextFactory 或每个请求有一个 ObjectContext 之间进行选择.

Also take a look at this Stackoverflow question, which talks about choosing between a IObjectContextFactory or having a ObjectContext per request.

这篇关于在 ASP.NET 中管理实体框架 ObjectContext的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆