使用 ASP.NET MVC、Linq To SQL 和 StructureMap 导致 DataContext 缓存数据
我将首先介绍我的项目设置:
- 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
从 StructureMap google 群组中的 Jeremy Miller 得到了这样的回复:
轻松赚钱,您自己在注册中创建 DataContext 对象的实例,这实际上使其成为整个 StructureMap 生态系统中的单例。
此代码:
需要使用 -deferred- 执行来定义 DataContext,而不是使用预构建的“New DCSDataContext()”
如果您使用的是 C# (因为我不知道 VB 语法),你会这样做:
我通过 C# 到 VB 转换器运行了这个,它给了我这个:
效果很好!
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:
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:
I ran this through a C# to VB converter and it gave me this:
Which works great!