检测单个实体是否需要在EF4和WPF中保存

时间:2011-04-21 13:37:39

标签: wpf xaml entity-framework-4 drag-and-drop binding

我正在努力检测EF4中的实体是否有需要保存的更改。

离开.NET几年之后,生锈绝对是我用来描述我现在所处位置的词。我正在尝试学习使用EF4和WPF,同时重新认识自己的.NET。我已经关注了Drag&amp ;;的一些教程。使用实体框架和WPF删除数据绑定,并构建一个带有少量Windows的应用程序,让我的知识逐渐增加。

我使用模型的最简单部分进行我的训练练习,模型有实体:网络和实验室,网络和实验室之间有多对多的链接,即NetworkLabs,这种关系并不是特别重要现在我仍然处于非常基础的状态。

我有一个窗口,显示列表框中的网络列表,旁边有一个DataGrid,显示网络中的实验室。我能够非常轻松地按照教程进行操作,最终得到的代码如下:

Public Class NetworkListWindow

Private Function GetNetworksQuery(entities As UKNEQASEntities) As ObjectQuery(Of Network)

    Dim networksQuery As ObjectQuery(Of Network) = entities.Networks
    ' Update the query to include NetworkLabs data in Networks.
    networksQuery = networksQuery.Include("NetworkLabs")
    ' Returns an ObjectQuery
    Return networksQuery

End Function

Private Sub Window_Loaded(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles MyBase.Loaded

    Dim entities As UKNEQASEntities = New UKNEQASEntities()
    ' Load data into Networks.
    Dim networksViewSource As CollectionViewSource = CType(Me.FindResource("UKNEQASEntitiesNetworksViewSource"), CollectionViewSource)
    Dim networksQuery As ObjectQuery(Of Network) = GetNetworksQuery(entities)
    networksViewSource.Source = networksQuery.Execute(MergeOption.AppendOnly)

End Sub

End Class

该窗口仅供查看,用户可以单击编辑按钮编辑所选网络。第二个窗口是我遇到问题的地方,在那个窗口我将网络实体从“数据源”窗口拖过来创建一个详细信息屏幕(行和列中带有标签和文本框的网格)。我最终得到的代码如下:

Public Class NetworkWindow

Private m_id As Integer
Private m_db As New UKNEQASEntities

Public Sub New(id As Integer)

    ' This call is required by the designer.
    InitializeComponent()

    ' Add any initialization after the InitializeComponent() call.
    m_id = id

End Sub

Private Function GetNetworkQuery() As ObjectQuery(Of Network)

    Dim networkQuery As ObjectQuery(Of Network) = m_db.Networks
    ' Update the query to include only the Network we are editing
    networkQuery = networkQuery.Where(Function(net) net.Id = m_id)
    ' Update the query to include NetworkLabs data in Networks.
    networkQuery = networkQuery.Include("NetworkLabs")
    ' Returns an ObjectQuery
    Return networkQuery

End Function

Private Sub Window_Loaded(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles MyBase.Loaded

    ' Load data into Networks.
    Dim networkViewSource As CollectionViewSource = CType(Me.FindResource("UKNEQASEntitiesNetworksViewSource"), CollectionViewSource)
    Dim networksQuery As ObjectQuery(Of Network) = GetNetworkQuery()
    networkViewSource.Source = networksQuery.Execute(MergeOption.AppendOnly)

    ' Get laboratories that are not in any networks
    Dim labResult = From laboratory In m_db.Laboratories _
                    Where _
                    Not _
                    (From networklab In m_db.NetworkLabs _
                     Select networklab.Laboratory.Id).Contains(laboratory.Id) _
                    Select laboratory

    Dim laboratoriesViewSource As CollectionViewSource = CType(Me.FindResource("UKNEQASEntitiesLaboratoriesViewSource"), CollectionViewSource)
    laboratoriesViewSource.Source = labResult.ToList

End Sub

End Class

这样可以很好地显示在前一个屏幕上选择的网络,我在工具栏上放了一个Save按钮,只需调用

m_db.SaveChanges()

保存更改并且也可以正常工作。当用户编辑数据并关闭窗口时我遇到了问题,我想检测当前网络是否需要保存回数据库以便我可以提示用户但我不知道如何获取网络检查。

我怀疑它与代码有关:

     Dim networkViewSource As CollectionViewSource = CType(Me.FindResource("UKNEQASEntitiesNetworksViewSource"), CollectionViewSource)
     Dim entry As ObjectStateEntry = m_db.ObjectStateManager.GetObjectStateEntry(....)

但我不知道如何让网络传递给GetObjectStateEntry。

在我之前的列表屏幕上,我可以通过从列表框中获取SelectedItem来获取所选网络,但是在单个输入窗口中找不到任何可以帮助我的内容。

我是以正确的方式来做这件事的吗?对于单一条目编辑屏幕,我仍然使用CollectionViewSource,就像我为列表屏幕所做的那样,这是最好的方式还是单个实体有什么东西?

我一直在寻找很多教程,而且我发现的大部分内容都是关于在DataGrids中显示数据进行编辑,这不是我想要的。我正在努力寻找任何有关编辑单个实体的屏幕的帮助,因此不知道如何获取用户正在编辑的实体的引用。

非常感谢任何帮助,因为我是这个EF和XAML云雀的新手。

1 个答案:

答案 0 :(得分:0)

你是从错误的角度看待它。开始使用EF时需要考虑的几件事情:

  • 你几乎不需要看 ObjectStateManager,这是一个东西 EF应该为你做。例如,如果你 想要关闭你的窗口并保存 一切,只需打电话 context.SaveChanges()并让EF为 找出需要的工作 储蓄什么不是。在某些情况下,您需要使用ObjectStateManager,但这些是特定的,通常与非常自定义的东西相关联。

  • 你没有看到很多例子, 因为正在构建WPF的人 和Silverlight应用程序不是 连接到数据库引擎, 相反,他们连接到一个或多个 Web服务层和交互层 跟他们。当你这样做时, 它首先发生的是你没有 使用“正常”EF工作时间更长 实体,这些都没有成为 序列化。您将使用其中之一 POCO自我跟踪实体 实体。

  • 如果您使用的是正常实体, 它们的设计始终如一 附加到上下文(在您的情况下 它将是:UKNEQASEntities),这个 意味着如果你试图使用它 在您将要的客户端应用程序中 确保你总是使用相同的 上下文,所以要么有参考 在Singleton类或注入它 它在依赖注入中 容器。如果你使用多个 上下文你会遇到一堆 与...有关的问题 给予对象的EntityKeys 与他们存在的背景有关 in(考虑上下文是一个记忆 您的数据库副本,但事实并非如此 在实践中,它更像是 您习惯使用的界面 自动生成SQL查询 您的数据库。

最后,如果你想构建一个好的WPF客户端应用程序,你还需要使用:

  • 依赖注入容器: MEF(部署在...上) a .Net部署)或Unity (这是企业的一部分 库)。
  • EF4 Self Tracking Entities(我 个人比POCO更好 对象,因为你得到了很多 强大的功能免费)。

如果你需要更多具体的帮助,你也可以直接戳我,我已经在这个问题上工作了一段时间,在中型到大型项目的专业开发团队。但是我从未在Visual Basic中工作过,所以当我必须阅读VB代码时,我会有点痛苦!