将 linq to sql datacontext 附加到业务层中的 httpcontext

发布于 2024-08-25 11:46:53 字数 740 浏览 1 评论 0原文

我需要我的 linq to sql 数据上下文可在我的业务/数据层上供我的所有存储库对象访问。然而,由于这是一个网络应用程序,我想根据请求创建和销毁它。我想知道是否有一个可以延迟创建数据上下文并将其附加到当前 HttpContext 的单例类是否可行。我的问题是:请求结束时数据上下文会自动处理吗?下面是我的想法的代码。这是否可以实现我的目的:拥有一个延迟可用并在请求结束时自动处置的线程安全数据上下文实例?

public class SingletonDC
{
    public static NorthwindDataContext Default
    {
        get
        {
            NorthwindDataContext defaultInstance = (NorthwindDataContext)System.Web.HttpContext.Current.Items["datacontext"];
            if (defaultInstance == null)
            {
                defaultInstance = new NorthwindDataContext();
                System.Web.HttpContext.Current.Items.Add("datacontext", defaultInstance);
            }
            return defaultInstance;
        }
    }
}

I need my linq to sql datacontext to be available across my business/data layer for all my repository objects to access. However since this is a web app, I want to create and destroy it per request. I'm wondering if having a singleton class that can lazily create and attach the datacontext to current HttpContext would work. My question is: would the datacontext get disposed automatically when the request ends? Below is the code for what I'm thinking. Would this accomplish my purpose: have a thread-safe datacontext instance that is lazily available and is automatically disposed when the request ends?

public class SingletonDC
{
    public static NorthwindDataContext Default
    {
        get
        {
            NorthwindDataContext defaultInstance = (NorthwindDataContext)System.Web.HttpContext.Current.Items["datacontext"];
            if (defaultInstance == null)
            {
                defaultInstance = new NorthwindDataContext();
                System.Web.HttpContext.Current.Items.Add("datacontext", defaultInstance);
            }
            return defaultInstance;
        }
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

始于初秋 2024-09-01 11:46:53

您的想象是有道理的 - 使用 HTTP 请求上下文来存储内容 - 但是不,存储在当前 HttpContext 中的一次性对象在请求结束时不会自动神奇地被处置。你必须以某种方式亲自处理它。

您可以轻松挂钩“结束请求”事件,例如使用放入 Global.asax.cs 中的代码。在 Application_EndRequest() 方法中,您可以对列表中需要它的每个对象手动调用 Dispose()

一种方法是迭代上下文中的每个项目,测试 IDisposable,然后在适当的情况下调用 Dispose。

protected void Application_EndRequest(Object sender, EventArgs e)
{
    foreach (var key in HttpContext.Current.Items.Keys) 
    {
        var disposable = HttpContext.Current.Items[key] as IDisposable;
        if (disposable != null)
        { 
           disposable.Dispose();
           HttpContext.Current.Items[key] = null; 
        } 
    }
}

我认为应该这样做。 ASPNET 不会自动为您执行此操作。当然,在真正的应用程序中使用此代码之前,您需要防止异常等情况。


Vertigo 的 Keith Craig 写道 不久前关于该主题的相关帖子,描述了您想要作为一种模式做什么,换句话说,一种做应该做的事情的方式重复。他提供了一个类来帮助解决这个问题,延迟加载数据库上下文并将其放入当前上下文中。这种方法存在一些陷阱 - 您可以在该帖子的评论讨论中阅读它们。评论中还引用了一堆相关文章。

What you imagine makes sense - using the HTTP Request context to store stuff - but No, disposable objects stored in the current HttpContext will not auto-magically be disposed when the request ends. You will have to hande that yourself, somehow.

There is an "End Request" event that you can hook into easily, for example using code that you drop into Global.asax.cs. In your Application_EndRequest() method, you can call Dispose() manually on each object in the list that requires it.

One way to do it is to iterate through each item in the context, test for IDisposable, and then call Dispose if appropriate.

protected void Application_EndRequest(Object sender, EventArgs e)
{
    foreach (var key in HttpContext.Current.Items.Keys) 
    {
        var disposable = HttpContext.Current.Items[key] as IDisposable;
        if (disposable != null)
        { 
           disposable.Dispose();
           HttpContext.Current.Items[key] = null; 
        } 
    }
}

I think that oughtta do it. ASPNET doesn't do this for you automatically. Of course you need protection from exceptions and so on, before using this code in a real app.


Keith Craig of Vertigo wrote a relevant post on the topic a while ago, describing what you want to do as a pattern, in other words a way of doing things that ought to be repeated. He provides a class to help out with that, to lazy load the DB context and drop it into the current context. There are some pitfalls with the approach - you can read about them in the comment discussion on that post. Also there are a bunch of related articles cited in the comments.

饮湿 2024-09-01 11:46:53

Cheeso 的代码将生成 InvalidOperationException “集合已修改;枚举操作可能无法执行”,因为它正在尝试修改正在迭代的 HttpContext 项。

您可以使用列表的副本来防止这种情况。

protected void Application_EndRequest(Object sender, EventArgs e)
{
    var keys = new ArrayList(HttpContext.Current.Items.Keys);

    foreach (var key in keys)
    {
        var disposable = HttpContext.Current.Items[key] as IDisposable;
        if (disposable != null)
        {
            disposable.Dispose();
            HttpContext.Current.Items[key] = null;
        }
    }
}

Cheeso's code will generate an InvalidOperationException "Collection was modified; enumeration operation may not execute" because it is trying to modify the HttpContext items that it's iterating over.

You can use a copy of the list to prevent this.

protected void Application_EndRequest(Object sender, EventArgs e)
{
    var keys = new ArrayList(HttpContext.Current.Items.Keys);

    foreach (var key in keys)
    {
        var disposable = HttpContext.Current.Items[key] as IDisposable;
        if (disposable != null)
        {
            disposable.Dispose();
            HttpContext.Current.Items[key] = null;
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文