使用 ASP.NET MVC、Linq To SQL 和 StructureMap 导致 DataContext 缓存数据

发布于 2024-08-26 12:54:51 字数 3319 浏览 6 评论 0原文

我将首先介绍我的项目设置:

  • ASP.NET MVC 1.0
  • StructureMap 2.6.1
  • VB

我创建了一个引导程序类,如下所示:

Imports StructureMap
Imports DCS.Data
Imports DCS.Services

Public Class BootStrapper

    Public Shared Sub ConfigureStructureMap()

        ObjectFactory.Initialize(AddressOf StructureMapRegistry)

    End Sub

    Private Shared Sub StructureMapRegistry(ByVal x As IInitializationExpression)

        x.AddRegistry(New MainRegistry())
        x.AddRegistry(New DataRegistry())
        x.AddRegistry(New ServiceRegistry())
        x.Scan(AddressOf StructureMapScanner)

    End Sub

    Private Shared Sub StructureMapScanner(ByVal scanner As StructureMap.Graph.IAssemblyScanner)

        scanner.Assembly("DCS")
        scanner.Assembly("DCS.Data")
        scanner.Assembly("DCS.Services")
        scanner.WithDefaultConventions()

    End Sub

End Class

我创建了一个控制器工厂,如下所示:

Imports System.Web.Mvc
Imports StructureMap

Public Class StructureMapControllerFactory
    Inherits DefaultControllerFactory

    Protected Overrides Function GetControllerInstance(ByVal controllerType As System.Type) As System.Web.Mvc.IController

        Return ObjectFactory.GetInstance(controllerType)

    End Function

End Class

我修改了 Global.asax.vb如下所示:

...
    Sub Application_Start()

        RegisterRoutes(RouteTable.Routes)

        'StructureMap
        BootStrapper.ConfigureStructureMap()
        ControllerBuilder.Current.SetControllerFactory(New StructureMapControllerFactory())

    End Sub
...

我已将结构映射注册表文件添加到我的三个项目中的每一个:DCS、DCS.Data 和 DCS.Services。这是 DCS.Data 注册表:

Imports StructureMap.Configuration.DSL

Public Class DataRegistry
    Inherits Registry

    Public Sub New()

        'Data Connections.
        [For](Of DCSDataContext)() _
            .HybridHttpOrThreadLocalScoped _
            .Use(New DCSDataContext())

        'Repositories.
        [For](Of IShiftRepository)() _
            .Use(Of ShiftRepository)()

        [For](Of IMachineRepository)() _
            .Use(Of MachineRepository)()

        [For](Of IShiftSummaryRepository)() _
            .Use(Of ShiftSummaryRepository)()

        [For](Of IOperatorRepository)() _
            .Use(Of OperatorRepository)()

        [For](Of IShiftSummaryJobRepository)() _
            .Use(Of ShiftSummaryJobRepository)()

    End Sub

End Class

就加载依赖项而言,一切都运行良好,但我在使用 Linq2SQL 类生成的 DCSDataContext 类时遇到问题。

我有一个发布到详细信息页面 (/Summary/Details) 的表单,该页面从 SQL 加载一些数据。然后,我有一个按钮可以在 JQuery 中打开一个对话框,该按钮根据对 (/Operator/Modify) 的请求填充该对话框。在对话框中,表单有一个组合框和一个“确定”按钮,允许用户更改操作员的名称。单击“确定”后,表单将发布到(/Operator/Modify)并通过我的程序的服务和存储层发送,并更新数据库中的记录。然后,调用 RedirectToAction 将用户返回到详细信息页面 (/Summary/Details),其中再次调用从 SQL 提取数据,更新详细信息视图。

一切都很好,除了详细信息视图不显示所选的新操作员。我可以单步执行代码并看到 DCSDataContext 类被访问以更新运算符(这实际上更改了数据库记录),但是当访问 DCSDataContext 来重新加载详细信息对象时,它会提取旧值。我猜测 StructureMap 不仅导致 DCSDataContext 类而且还导致数据被缓存?

我还尝试将以下内容添加到 Global.asax 中,但它最终导致程序崩溃,告诉我 DCSDataContext 已被处理...

Private Sub MvcApplication_EndRequest(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.EndRequest

   StructureMap.ObjectFactory.ReleaseAndDisposeAllHttpScopedObjects()

End Sub

有人可以帮忙吗?

I'll start by telling my project setup:

  • ASP.NET MVC 1.0
  • StructureMap 2.6.1
  • VB

I've created a bootstrapper class shown here:

Imports StructureMap
Imports DCS.Data
Imports DCS.Services

Public Class BootStrapper

    Public Shared Sub ConfigureStructureMap()

        ObjectFactory.Initialize(AddressOf StructureMapRegistry)

    End Sub

    Private Shared Sub StructureMapRegistry(ByVal x As IInitializationExpression)

        x.AddRegistry(New MainRegistry())
        x.AddRegistry(New DataRegistry())
        x.AddRegistry(New ServiceRegistry())
        x.Scan(AddressOf StructureMapScanner)

    End Sub

    Private Shared Sub StructureMapScanner(ByVal scanner As StructureMap.Graph.IAssemblyScanner)

        scanner.Assembly("DCS")
        scanner.Assembly("DCS.Data")
        scanner.Assembly("DCS.Services")
        scanner.WithDefaultConventions()

    End Sub

End Class

I've created a controller factory shown here:

Imports System.Web.Mvc
Imports StructureMap

Public Class StructureMapControllerFactory
    Inherits DefaultControllerFactory

    Protected Overrides Function GetControllerInstance(ByVal controllerType As System.Type) As System.Web.Mvc.IController

        Return ObjectFactory.GetInstance(controllerType)

    End Function

End Class

I've modified the Global.asax.vb as shown here:

...
    Sub Application_Start()

        RegisterRoutes(RouteTable.Routes)

        'StructureMap
        BootStrapper.ConfigureStructureMap()
        ControllerBuilder.Current.SetControllerFactory(New StructureMapControllerFactory())

    End Sub
...

I've added a Structure Map registry file to each of my three projects: DCS, DCS.Data, and DCS.Services. Here is the DCS.Data registry:

Imports StructureMap.Configuration.DSL

Public Class DataRegistry
    Inherits Registry

    Public Sub New()

        'Data Connections.
        [For](Of DCSDataContext)() _
            .HybridHttpOrThreadLocalScoped _
            .Use(New DCSDataContext())

        'Repositories.
        [For](Of IShiftRepository)() _
            .Use(Of ShiftRepository)()

        [For](Of IMachineRepository)() _
            .Use(Of MachineRepository)()

        [For](Of IShiftSummaryRepository)() _
            .Use(Of ShiftSummaryRepository)()

        [For](Of IOperatorRepository)() _
            .Use(Of OperatorRepository)()

        [For](Of IShiftSummaryJobRepository)() _
            .Use(Of ShiftSummaryJobRepository)()

    End Sub

End Class

Everything works great as far as loading the dependecies, but I'm having problems with the DCSDataContext class that was genereated by Linq2SQL Classes.

I have a form that posts to a details page (/Summary/Details), which loads in some data from SQL. I then have a button that opens a dialog box in JQuery, which populates the dialog from a request to (/Operator/Modify). On the dialog box, the form has a combo box and an OK button that lets the user change the operator's name. Upon clicking OK, the form is posted to (/Operator/Modify) and sent through the service and repository layers of my program and updates the record in the database. Then, the RedirectToAction is called to send the user back to the details page (/Summary/Details) where there is a call to pull the data from SQL again, updating the details view.

Everything works great, except the details view does not show the new operator that was selected. I can step through the code and see the DCSDataContext class being accessed to update the operator (which does actually change the database record), but when the DCSDataContext is accessed to reload the details objects, it pulls in the old value. I'm guessing that StructureMap is causing not only the DCSDataContext class but also the data to be cached?

I have also tried adding the following to the Global.asax, but it just ends up crashing the program telling me the DCSDataContext has been disposed...

Private Sub MvcApplication_EndRequest(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.EndRequest

   StructureMap.ObjectFactory.ReleaseAndDisposeAllHttpScopedObjects()

End Sub

Can someone please help?

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

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

发布评论

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

评论(1

孤独岁月 2024-09-02 12:54:51

从 StructureMap google 群组中的 Jeremy Miller 得到了这样的回复:

轻松赚钱,您自己在注册中创建 DataContext 对象的实例,这实际上使其成为整个 StructureMap 生态系统中的单例。

此代码:

'Data Connections. 
[For](Of DCSDataContext)() _ 
    .HybridHttpOrThreadLocalScoped _ 
    .Use(New DCSDataContext()) 

需要使用 -deferred- 执行来定义 DataContext,而不是使用预构建的“New DCSDataContext()”

如果您使用的是 C# (因为我不知道 VB 语法),你会这样做:

For<DCSDataContext>().HybridHttpOrThreadLocalScoped().Use(() => new DCSDataContext()); 

我通过 C# 到 VB 转换器运行了这个,它给了我这个:

[For](Of DCSDataContext)() _
    .HybridHttpOrThreadLocalScoped _
    .Use(Function() New DCSDataContext())

效果很好!

Got this response back from Jeremy Miller on the StructureMap google group:

Easy money, you're creating an instance of your DataContext object -yourself- in the registration, which de facto makes that a singleton throughout the StructureMap ecosystem.

This code:

'Data Connections. 
[For](Of DCSDataContext)() _ 
    .HybridHttpOrThreadLocalScoped _ 
    .Use(New DCSDataContext()) 

Needs to define the DataContext using -deferred- execution rather than using the pre-built "New DCSDataContext()"

If you were in C# (because I don't know the VB syntax), you would do:

For<DCSDataContext>().HybridHttpOrThreadLocalScoped().Use(() => new DCSDataContext()); 

I ran this through a C# to VB converter and it gave me this:

[For](Of DCSDataContext)() _
    .HybridHttpOrThreadLocalScoped _
    .Use(Function() New DCSDataContext())

Which works great!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文