Whenever I create a dynamic DNN module in VS, the installed DNN template automatically creates a DataProvider, with a shared object for the Data Provider as follows:
#Region "Shared/Static Methods"
' singleton reference to the instantiated object
Private Shared objProvider As DataProvider = Nothing
' constructor
Shared Sub New()
CreateProvider()
End Sub
' dynamically create provider
Private Shared Sub CreateProvider()
objProvider = CType(Framework.Reflection.CreateObject("data", NameSpace, ""), DataProvider)
End Sub
' return the provider
Public Shared Shadows Function Instance() As DataProvider
Return objProvider
End Function
#End Region
Now, controllers are intended to use Instance to obtain the shared copy of the Provider, and execute operations. There might be Threading issues with this approach according to me.
Firstly, this approach cannot support transactions.
More importantly, this approach can lead to inconsistencies. Suppose, this provider is for manipulating 'Department' entity in an application.
Now, suppose 2 users are simultaneously adding departments by calling AddDept whose definition is:
1) Public Overrides Function AddDepartment(ByVal info As DepartmentInfo) As Integer
2) Return (SqlHelper.ExecuteNonQuery(ConnectionString, GetFullyQualifiedName("AddDepartment"), _
3) info.portalId, info.name, info.acronym))
4) End Function
After 1st user's Thread for creating Department reached Line 1), suppose the OS context switches to the Thread of the other user also creating a department. Now, info has been populated with the data from First user, when the context switch occurs.
After the switch, info is poplulated with data from 2nd user, and is successfully entered via ExecuteNonQuery. Then, the control returns back to the Thread of the first user. The important point to remember is that both used Instance() to get a copy of the provider, which returned the shared copy.
So, the AddDept method's Activation Record in memory would be same for both Threads. When the control returns to 1st user's thread, "info" reference in this activation record has effectively been over-written by 2nd user's data.
So, when ExecuteNonQuery() happens for the first user, it is actually the second user's data which is being inserted.
Anyone, feels this is a valid problem??? And if yes, then the entire DNN provider model is at question!!!
One point to notice here is that the problem does not reside with the Provider Model, but the practise of sharing the Provider instance. A new Instance for each request would never lead to this problem!!!