0

I know this question has been asked and discussed a lot (e.g. Here and Here and this Article). Nevertheless, i still feel confused about it. I know that DbContexts should not live for the duration of application lifetime, i know they should be used per Form (window) or per Presenter. The problem is that i don't have Forms or Presenters. I have a single Form (Window) with many view models, some of them which live for the duration of the application and almost all of my view models depend on DbContext (LOB application, WPF, MVVM, Sql Server CE).
My solution is to hide DbContext behind a factory which is injected in all view models that need access to DbContext and those view models create/dispose of the DbContext when their corresponding view is loaded/unloaded. I would like to know if this solution has any problems or if there is a better solution you could advise ?

Community
  • 1
  • 1
Ibrahim Najjar
  • 18,190
  • 4
  • 65
  • 91

1 Answers1

0

I tend to lay my projects out as follows;

1) Presentation Layer:

Contains my Views and ViewModels

2) Business Layer:

Contains my business logic

3) Data Layer:

Contains my models

My Presentation layer calls into the business layer to populate local copies (held in the ViewModel) of the data I wish to use in my ViewModel / View.

This is achieved with a Using statement, something like;

Using DBContext As Entities = ConnectToDatabase()

    Dim clsApprovalTypes As New Repositories.clsApprovalTypesRepository(DBContext)

    dbResults = clsApprovalTypes.GetRecords()

End Using

Return dbResults

Here I simply pass in the Context into Repository, once the data has been returned, the "End Using" will dispose of my context.

To update the context with changes made in my ViewModel / View, I use an AddEdit routine, which accepts a record, and updates / Adds to the context as necessary, using a similar methodology to the above, something like;

Using DBContext As CriticalPathEntities = ConnectToDatabase()

        Dim clsApprovalTypes As New Repositories.clsApprovalTypesRepository(DBContext)

        clsApprovalTypes.AddEditRecord(ApprovalTypeToSave)

        Try

            clsApprovalTypes.SaveData()

        Catch ex As Exception

            Return ex

        End Try

End Using

Where my AddEdit routine is something like;

SavedRecord = New ApprovalType                'Store the Saved Record for use later

Dim query = From c In DBContext.ApprovalTypes
                    Where c.ApprovalType_ID = RecordToSave.ApprovalType_ID
                    Select c

If query.Count > 0 Then

    SavedRecord = query.FirstOrDefault

End If

'
' Use Reflection here to copy all matching Properties between the Source Entity
' and the Entity to be Saved...
'
SavedRecord = Classes.clsHelpers.CopyProperties(RecordToSave, SavedRecord)

If query.Count = 0 Then

    Try

        DBContext.ApprovalTypes.Add(SavedRecord)

    Catch ex As EntityException

        Return ex

    End Try

End If

I wrote a little more about some of this here;

https://stackoverflow.com/a/15014599/1305169

Community
  • 1
  • 1
PGallagher
  • 3,037
  • 2
  • 23
  • 36
  • Thanks for detailed explanation, from what i see in your method, you're using the context per method and disposing it when the method is finished, but i think this goes against what the article i linked too advices and calls this a micro usage of the context instead of letting the context live per method, let it live per presenter. – Ibrahim Najjar May 25 '13 at 00:15
  • 1
    Yeah, I based my answer on the recommendation by Microsoft given here... http://msdn.microsoft.com/en-gb/library/cc853327.aspx, which recommends that the Context be enclosed in a `Using` statement. – PGallagher May 25 '13 at 08:30
  • 1
    Your recommendation is correct and i would use a "using" statement in MVC applications inside a controller action method or inside a WCF service method.Plus, the link you shared says that if there is a binding and the context needs to live for the duration of the binding then you should dispose it manually. So i guess this is my situation, so i will consider this as the answer unless someone else comes up with another idea. – Ibrahim Najjar May 25 '13 at 11:03