I'll start by telling my project setup:
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?
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!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With