【问题标题】:How can this be done with (N)Hibernate?(N)Hibernate如何做到这一点?
【发布时间】:2010-03-16 00:36:39
【问题描述】:

我正在使用 NHibernate 创建一个 Windows 窗体应用程序。它是一个 MDI 应用程序,因此用户可以同时打开多少个表单(可能很多)没有限制。

对于大多数表单,我希望有一个“确定”和一个“取消”按钮。两者都关闭表单,但“确定”也会将修改后的数据保存到数据库中。表单可能非常复杂,修改可能会触及整个对象图,添加一些、删除一些和更改更多。如果可以根据需要自动检测并保留更改,而不需要手动跟踪每个更改,那就太好了。

什么是这样做的好方法?

额外信息:我可以制作任何我想要的数据库架构。我正在使用 MSSQL 2008,目前已决定使用 GUID 主键(使用 guid.comb 生成器)和用于乐观并发的 TIMESTAMP 列。

我尝试简单地将 NHibernate ISessionFlushMode 设置为 Never,根据需要进行所有修改,然后在用户单击 OK 时调用 Flush()But that didn't work.

【问题讨论】:

    标签: winforms nhibernate hibernate


    【解决方案1】:

    一些可能的解决方案,假设您为每个表单实例使用一个 ISession:

    1. 如果用户取消,则调用 ISession.Clear。
    2. 将 FlushMode 设置为 Commit 并仅在用户单击确定时启动事务。
    3. 坚持使用手动刷新模式的original approach。它应该可以工作,并且您看到的行为不是错误。

    由于您将 GUID 用于主键,因此您不应遇到 NH 意外刷新会话的问题,因为它需要数据库生成标识符。您仍然需要注意在选择之前可能会刷新 NH 的情况,以确保结果一致。

    我认为您不必担心打开和关闭数据库连接。我的理解是 NH 非常善于管理这一点。

    【讨论】:

    • 如果不是bug,那我应该如何解决呢?因为用户创建对象的时间(例如,通过在网格视图中添加一行)和他修改它的时间完全不相关(他可能会随时返回)。我什么时候应该Save() 新对象?我是否应该仅在单击“确定”时手动跟踪所有新对象和Save()它们?
    • 这不是错误,因为它的行为与记录的一样:knol.google.com/k/fabio-maulo/nhibernate-chapter-9/…。当对象处于可以插入数据库的状态时,您应该调用Save()。 NHibernate 可以将插入推迟到Flush(),或者在生成 ID 的情况下,它可以立即插入。如果用户可以在网格中添加/更改/删除行,那么我会等到他们单击“确定”以确定需要插入哪些行。这取决于应用程序。
    • @Jamie Ide - 嗯,没错。我必须自己跟踪肮脏。或者至少是我猜的插入。顺便说一句 - 你是什么意思它被记录在案?我没有看到那里直接或间接提到这种特殊行为。
    • 我提供的文档链接详细描述了 Flush 的工作原理。您在其他问题中询问的行为是“SQL 语句按以下顺序发出”中描述的顺序的结果。当然,由您的代码决定何时通过调用 Save 使对象持久化。你为什么要跟踪脏?无论会话有未决更改,我提供的三个解决方案中的任何一个都可以工作。
    • 我想要跟踪脏数据,因为我想要一种简单的方法来实现 OK/Cancel 按钮。如果 NHibernate 会在 Flush()'ing 时生成 SQL,我根本不需要编写任何代码。也许我最好举个例子。我目前正在尝试制作一个用于编辑简单分类器的表单。 DB 表只有三列 - ID、名称和版本。自然,对象也是如此。我使用的表单由一个带有一列的 GridView 组成 - 名称。用户可以在其中添加/删除/更改行。
    【解决方案2】:

    这应该会有所帮助:NHibernate Best Practices with ASP.NET, 1.2nd Ed.(我知道它是 ASP.NET,但您应该会发现这些信息很有用并且可以轻松转移到 WinForms。)

    简而言之,应该为每个窗口架构选择一个会话。在这里,不可能为相同的任务打开两个不同的窗口是有意义的。然后,您可能希望在 Form_Load() 上创建 NHibernate ISession API 的实例。最后,如果用户点击 OK,那么就只需要 BeginTransaction(),Flush() 会话,Commit() 事务,否则回滚。

    【讨论】:

    • 坏主意。 NHibernate 事务只是 ADO.NET 事务的薄包装器。你能想象如果在用户使用表单时事务一直处于打开状态会发生什么?它会锁定多少个数据库表?
    • 你是对的,那么我真正的意思是保持会话打开,没有活动的事务。但是每次从数据库加载或写入数据库时​​,都要通过事务来完成。我已经编辑了我的答案以反映我的意思。
    【解决方案3】:

    也许您将整个事物包装在一个事务中并在用户单击“确定”时提交该事务?

    【讨论】:

    • 并在用户使用表单的整个过程中保持事务打开?想想锁定!
    猜你喜欢
    • 1970-01-01
    • 2011-03-12
    • 2016-03-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-19
    相关资源
    最近更新 更多