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

检测单个实体是否需要保存在EF4和WPF中,wpf,xaml,entity-framework-4,drag-and-drop,binding,Wpf,Xaml,Entity Framework 4,Drag And Drop,Binding,我正在努力检测EF4中的实体是否有需要保存的更改 离开.NET几年后,我肯定会用rusty这个词来形容我现在的处境。我正在努力学习使用EF4和WPF,同时用.NET重新认识自己。我已经学习了很多关于实体框架和WPF的拖放数据绑定的教程,并用几个窗口构建了一个应用程序,让我的知识一点一点地积累起来 我正在使用我的模型中最简单的部分进行训练练习,该模型有实体:网络和实验室,网络和实验室之间存在多对多的联系,即网络实验室,这种关系现在并不特别重要,因为我仍然处于最基本的阶段 我有一个窗口,在列表框中显

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

离开.NET几年后,我肯定会用rusty这个词来形容我现在的处境。我正在努力学习使用EF4和WPF,同时用.NET重新认识自己。我已经学习了很多关于实体框架和WPF的拖放数据绑定的教程,并用几个窗口构建了一个应用程序,让我的知识一点一点地积累起来

我正在使用我的模型中最简单的部分进行训练练习,该模型有实体:网络和实验室,网络和实验室之间存在多对多的联系,即网络实验室,这种关系现在并不特别重要,因为我仍然处于最基本的阶段

我有一个窗口,在列表框中显示网络列表,旁边有一个数据网格,显示网络中的实验室。根据教程,我可以很容易地做到这一点,最后我得到了如下代码:

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
     Dim networkViewSource As CollectionViewSource = CType(Me.FindResource("UKNEQASEntitiesNetworksViewSource"), CollectionViewSource)
     Dim entry As ObjectStateEntry = m_db.ObjectStateManager.GetObjectStateEntry(....)
该窗口仅用于查看,用户可以单击编辑按钮编辑所选网络。第二个窗口是我遇到问题的地方,在该窗口中,我从“数据源”窗口拖动网络实体,创建一个详细信息屏幕,在行和列中创建一个带有标签和文本框的网格。我最终得到了如下代码:

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
     Dim networkViewSource As CollectionViewSource = CType(Me.FindResource("UKNEQASEntitiesNetworksViewSource"), CollectionViewSource)
     Dim entry As ObjectStateEntry = m_db.ObjectStateManager.GetObjectStateEntry(....)
这对于显示在上一个屏幕上选择的网络很好,我在工具栏上放了一个保存按钮,它只需调用

m_db.SaveChanges()
保存更改,这样也可以正常工作。我的问题是,当用户编辑数据并关闭窗口时,我想检测当前网络是否需要保存回数据库,以便我可以提示用户,但我不知道如何获取网络以进行检查

我怀疑这与以下代码有关:

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
     Dim networkViewSource As CollectionViewSource = CType(Me.FindResource("UKNEQASEntitiesNetworksViewSource"), CollectionViewSource)
     Dim entry As ObjectStateEntry = m_db.ObjectStateManager.GetObjectStateEntry(....)
但我不知道如何让网络传递到GetObjectStateEntry

在我以前的列表屏幕上,我可以通过从列表框中获取SelectedItem来获取所选网络,但在我的单个输入窗口中找不到任何有助于我的东西

我这样做对吗?对于单条目编辑屏幕,我仍然像列表屏幕一样使用CollectionViewSource,这是最好的方法还是对单个实体有什么好处

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


非常感谢您的帮助,因为我是EF和XAML lark的新手。

您从错误的角度看待它。当你开始使用EF时需要考虑的几个问题:

你几乎不需要看 ObjectStateManager,这是一个 EF应该为你做些什么。例如,如果你 要关闭窗口并保存吗 一切,打电话就行了 context.SaveChanges并让EF 找出需要什么的工作 存钱什么的。在某些情况下,您需要使用ObjectStateManager,但这些都是特定的,并且通常与非常定制的内容相关联

你看到的例子不多, 因为建造WPF的人 而Silverlight应用程序并非如此 连接到数据库引擎, 相反,它们连接到一个或多个 Web服务层和交互层 和他们在一起。当你这样做的时候 发生的第一件事是你没有 长时间使用正常EF 实体,这些并不是被制造出来的 连载。你将与任何一方合作 自跟踪的POCO实体 实体

如果使用的是法线实体, 它们被设计用于所有方面 附加到您案例中的上下文 它将是:英国公民,这个 意味着如果您尝试使用此 在客户端应用程序中,您将需要 确保您始终使用相同的 上下文,所以两者都有一个引用 在Singleton类或inject上执行此操作 它是在依赖注入中实现的 容器如果使用多个 你会遇到很多人 与该计划有关的问题 指定给对象的EntityKey 就其存在的背景而言 在上下文中考虑记忆 数据库的副本,这不是 事实上,它的工作原理更像 您用来 自动生成针对的sql查询 你的数据库

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

依赖项注入容器: 部署在 Net部署或 哪个是企业的一部分 图书馆 EF4 I 我个人喜欢这些而不是POCO 对象,因为你会得到很多 免费提供强大的功能。 如果你需要更具体的帮助,你也可以直接打电话给我,我已经在中大型项目的专业开发团队中工作了一段时间。然而,我从来没有工作过
VisualBasic,所以当我不得不阅读VB代码时,我有点痛苦

感谢您的回复,我想我正在进入一个痛苦的世界,在WPF示例中遵循MS的EF4。示例显示了将两个实体绑定到主窗口上的ListBox/datagrids,然后显示创建一个save按钮来调用上下文中的.SaveChanges,然后停止。我正在尝试构建一个应用程序,其中有少量实体,它们之间有很多关系,用户需要能够进行更改、保存更改、恢复更改,取消这些内容,因此在扩展我对MS示例的理解时,我很难应用所有这些内容。我按照您的建议将我的上下文放在一个Singleton类上,我的编辑窗口现在可以检测是否有需要保存的更改,这样我就可以给用户一个标准提示:是否要保存更改?Yes调用。SaveChanges、cancel停止关闭窗口,而No在恢复更改时不执行任何操作。当一个单例类的上下文不做任何事情时,意味着编辑后的网络仍然拥有我返回上一个窗口时所做的所有更改。有没有一种简单的方法可以还原上下文中的更改?