将生成的ADO.Net DbContext生成到View-Models的最佳方法

时间:2012-08-05 19:55:01

标签: wpf entity-framework mvvm ado.net dbcontext

我目前正在使用MVVM Light作为MVVM框架,Entity Framework作为ORM,以及MS Synch Framework作为将本地Sql Compact DB与在线SQL数据库同步的手段来处理WPF MVVM应用程序。该应用程序的范围也相当复杂,因为它旨在管理资产,计算资产在其生命周期内的使用损耗。值得庆幸的是,我是所有这些技术的新手,所以无知是幸福:)我发现了许多有关创建工作单元模式和存储库模式的教程和信息。但是,我正在使用新的DbContext,我读过它已经使用了这两种模式。

我当前的问题与在Entity Framework中使用新的DbContext有关。我在VS中使用过DbContext Generator模板,所以我有一个MyDbModelContainer。我直接从我的视图模型中使用它,它为每个VM创建一个Context,我很确定这是一个坏主意。这是我的父/子类型数据输入场景的构造函数,我在这里构造容器,并且他们使用MVVM Light将选定项目发送到子VM。

  Private FatigueDbContext As FatigueModelContainer

Public Sub New()

    If IsInDesignMode = False Then

        FatigueDbContext = New FatigueModelContainer

        FatigueDbContext.CtMaterials.Load()
        CtMaterialsCollection = FatigueDbContext.CtMaterials.Local

        FatigueDbContext.CtManufactures.Load()
        CtManufactures = FatigueDbContext.CtManufactures.Local

    End If

End Sub

我想在我的View-Model的生命周期中保持Context打开,以便我可以使用MyDbModelContainer.MyTable.Local进行绑定。因此,虽然这有效,但我该如何正确处理?

我的直觉是我需要以某种方式将自动生成的MyDbModelContainer包装到某些类中,这些类基本上只包含我需要在该View-Model上使用的表和函数。

我没有使用View-Model Locator,而是使用另一个View-Model来管理我的视图,从Rachel's blog得到了这个想法,我喜欢这个概念。但是,这意味着我正在创建所有的View-Models,并预先初始化任何视图模型依赖项。我只有一个窗口,我只是在View-Models之间切换它们留在内存中,当切换到新的View-Model时我没有办法关闭我的DbContext。

以下是Shell View-Model

的代码
Public Class ShellViewModel
Inherits ViewModelBase

#Region "Fields"

Private _changePageCommand As ICommand
Private _currentPageViewModel As IPageViewModel
Private _pageViewModels As List(Of IPageViewModel)

#End Region

Public Sub New()
    Dim DialogService As New ModalDialogService

    ' Add available pages
    PageViewModels.Add(New ImportJobDataViewModel(DialogService))
    PageViewModels.Add(New TestViewModel())
    PageViewModels.Add(New ReverseBendUtilityViewModel(DialogService))

    ' Set starting page
    CurrentPageViewModel = PageViewModels(0)
End Sub

#Region "Properties / Commands"

Public ReadOnly Property ChangePageCommand() As ICommand
    Get
        If _changePageCommand Is Nothing Then

            _changePageCommand = New RelayCommand(Of IPageViewModel)(Sub(param) ChangeViewModel(param))

        End If
        Return _changePageCommand
    End Get
End Property

Private Function IsViewPageModel(viewPageModel As IPageViewModel) As Boolean
    If TypeOf (viewPageModel) Is IPageViewModel Then
        Return True
    Else
        Return False
    End If
End Function

Public ReadOnly Property PageViewModels() As List(Of IPageViewModel)
    Get
        If _pageViewModels Is Nothing Then
            _pageViewModels = New List(Of IPageViewModel)()
        End If
        Return _pageViewModels
    End Get
End Property

Public Property CurrentPageViewModel() As IPageViewModel
    Get
        Return _currentPageViewModel
    End Get
    Set(value As IPageViewModel)
        If _currentPageViewModel IsNot value Then
            _currentPageViewModel = value
            RaisePropertyChanged(Function() CurrentPageViewModel)
        End If
    End Set
End Property

#End Region

#Region "Methods"

Private Sub ChangeViewModel(viewModel As IPageViewModel)
    If Not PageViewModels.Contains(viewModel) Then
        PageViewModels.Add(viewModel)
    End If

    CurrentPageViewModel = PageViewModels.FirstOrDefault(Function(vm) vm Is viewModel)
End Sub

#End Region

End Class 

总而言之......除了自动生成的FatigueModelContainer之外,我应该创建一个单独的类,该类看起来是什么样的,它只是一个类,还是基于它的单独类业务运营。例如添加,更新和删除制造的类,添加,更新和删除材料的类等等。我应该将它插入VM?大概是在Shell-View-Model?

1 个答案:

答案 0 :(得分:0)

您可以在不真正触及数据库上下文的情况下解决此问题。我们的想法是,即使VM保留在内存中,您也只需要在VM的视图处于活动状态时初始化模型实例。

Caliburn.Micro: Screens and Conductors中有一种很好的方法可以解决这个问题,但它并不是特定于mvvm框架的。

在最基本的情况下,正如Rachel在上面的评论中提到的那样,您将IPageViewModel扩展为包含处理VM的激活和停用逻辑的函数:激活VM时调用激活逻辑,当VM被停用时,将调用停用逻辑。

激活/取消激活的实际调用将在IPageViewModels的容器中进行,例如:

Public Property CurrentPageViewModel() As IPageViewModel
    Get
        Return _currentPageViewModel
    End Get
    Set(value As IPageViewModel)
        If _currentPageViewModel Is value Then
            Return
        End If

        If _currentPageViewModel IsNot Nothing Then
            _currentPageViewModel.Deactivate()
        End If

        _currentPageViewModel = value

        If value IsNot Nothing Then
            value.Activate()
        End If    

        RaisePropertyChanged(Function() CurrentPageViewModel)
    End Set
End Property

这样,您可以在停用页面时关闭数据库连接/分离DbContext,并在激活页面时将其打开。