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

发布于 2024-11-03 03:39:21 字数 3966 浏览 0 评论 0原文

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

离开 .NET 几年后,我肯定会用“生锈”这个词来形容我现在的处境。我正在尝试学习使用 EF4 和 WPF,同时重新熟悉 .NET。我已经学习了许多关于 Drag & 的教程。放弃使用实体框架和 WPF 进行数据绑定,并使用一些 Windows 构建一个应用程序,这让我的知识一点点增长。

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

我有一个窗口,在列表框中显示网络列表,旁边有一个数据网格,显示网络中的实验室。我能够按照教程相当轻松地做到这一点,最终得到如下代码:

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

这对于显示在上一个屏幕上选择的网络效果很好,我在工具栏上放置了一个“保存”按钮,该按钮只需调用“

m_db.SaveChanges()

保存更改”并且效果也很好。我的问题出现在满足用户编辑数据并关闭窗口时,我想检测当前网络是否需要保存回数据库,以便我可以提示用户,但我不知道如何获取网络检查。

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

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

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

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

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

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

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

I am struggling with detecting whether an entity in EF4 has changes that need saving.

After a few years away from .NET rusty is definitely the word I'd use to describe where I am right now. I am trying to learn to use EF4 and WPF while reacquainting myself with .NET. I've followed a number of tutorials on Drag & Drop Databinding with the Entity Framework and WPF and built an app with a few Windows that is getting my knowledge up little by little.

I am using the simplest part of my Model for my training exercises, The model has entities: Network and Laboratory, there is a many-to-many link between Networks and Labs, namely NetworkLabs, the relationship is not particularly important right now as I am still at the very basics.

I have a window that displays a list of Networks in a listbox, with a DataGrid next to it showing the Laboratories in the Network. I was able to do that fairly easily following the tutorials and I ended up with code like:

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

That window is for viewing only, the user can click an edit button to edit the selected network. That second window is where I am hitting problems, on that window I dragged the network entity over from the Data Sources window to create a details screen (a grid with labels and textboxes in the rows and columns). I ended up with code like:

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

And that works fine for showing the network that was selected on the previous screen, I put a Save button on a toolbar which simply calls

m_db.SaveChanges()

To save the changes and that works fine as well. My problem comes when catering for when the user edits the data and closes the window, I want to detect whether the current network needs saving back to the database so I can prompt the user but I don't know how to get hold of the network to check.

I suspect it is something to do with code like:

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

but I don't know how to get the network to pass to GetObjectStateEntry.

On my previous list screen I was able to get the selected network by getting the SelectedItem from the listbox but I can't find anything that would help me on my single entry window.

Am I going about this the right way? For the single entry edit screen I am still using CollectionViewSource like I did for the list screen, is that the best way or is there something for single entities?

I have been looking for lots of tutorials and the majority I find are all about displaying the data for editing in DataGrids which is not what I am looking for. I am struggling to find any help on making screens for editing single entities so don't know how to pick up a reference to the entity the user is editing.

Any help is greatly appreciated as I am a novice at this EF and XAML lark.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

往事风中埋 2024-11-10 03:39:21

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

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

  • 你没有看到很多例子,
    因为正在构建 WPF 的人们
    而 Silverlight 应用程序则不然
    连接到数据库引擎,
    相反,它们连接到一个或多个
    Web 服务层并进行交互
    和他们在一起。当您执行此操作时,
    首先发生的事情是你不
    使用“正常”EF 的工作时间更长
    实体,这些不是被创造出来的
    连载了。您将与以下任一方合作
    POCO 自跟踪实体
    实体。

  • 如果您使用普通实体,
    它们被设计为始终工作
    附加到上下文(在你的情况下
    它将是:UKNEQASentities),这个
    意味着如果您尝试使用此
    在客户端应用程序中你会想要
    确保您始终使用相同的
    上下文,所以要么有参考
    在 Singleton 类上或注入它
    它在依赖注入中
    容器。如果您使用多个
    你会遇到很多上下文
    的相关问题
    赋予对象的EntityKey
    与它们存在的背景相关
    在(将上下文视为记忆
    您的数据库的副本,这不是
    在实践中确实如此,它的工作原理更像是
    您使用的界面
    自动生成sql查询
    您的数据库。

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

  • 依赖注入容器:
    MEF(部署在
    .Net 部署)或 Unity
    (这是企业的一部分
    图书馆)。
  • EF4 自我跟踪实体(我
    个人更喜欢这些而不是 POCO
    对象,因为你得到了很多
    强大的功能免费)。

如果您需要更具体的帮助,也可以直接戳我,我已经在大中型项目的专业开发团队中使用这些东西有一段时间了。然而我从来没有使用过Visual Basic,所以当我必须阅读VB代码时我有点痛苦!

You are looking at it from the wrong perspective. Several things that you need to consider when you start using EF:

  • You hardly need to look at
    ObjectStateManager, this is something
    EF is supposed to do for you. For example if you
    want to close your Window and save
    everything, just call
    context.SaveChanges() and let EF to
    the work of finding out what needs
    saving and what not. There are cases where you need to use the ObjectStateManager, but these are specific and usually associated with very custom things.

  • You are not seeing many examples,
    because people that are building WPF
    and Silverlight applications aren't
    connected to Data Base engines,
    instead they connect to one or more
    layers of Web Services and interact
    with them. When you do this, the
    first thing it happens is that you no
    longer work with the "normal" EF
    entities, these weren't made to be
    serialized. You will work with either
    POCO Entities of Self Tracking
    Entities.

  • If you are using the normal Entities,
    they are designed to allways work
    attached to a context (in your case
    it would be: UKNEQASEntities), this
    means that if you attempt to use this
    in a client application you will want
    to make sure you allways use the same
    context, so either have a reference
    to it on a Singleton class or inject
    it in a Dependency Injection
    container. If you use multiple
    contexts you will come across a bunch
    of problems related with the
    EntityKeys which are given to objects
    in relation to the context they exist
    in (consider the context a memory
    copy of your Data Base, this isn't
    true in practice, it works more like
    an interface that you use to
    auto-generate sql queries against
    your Data Base.

In the end, if you want to build a good WPF client application you need to also use:

  • Dependency Injection container:
    either MEF (which is deployed on
    a .Net deployment) or Unity
    (which is part of the Enterprise
    Library).
  • EF4 Self Tracking Entities (I
    personally perfer these over POCO
    objects, because you get a lot of
    powerfull functionality for free).

You can also poke me directly if you need more specific help, I've been working with this stuff for a while now, in professional development teams on medium to large scale projects. However I have never worked in Visual Basic, so I have a bit of pain when I have to read VB code!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文