【问题标题】:How to handle entity creation/editing in a master-detail如何在主详细信息中处理实体创建/编辑
【发布时间】:2010-11-04 23:25:14
【问题描述】:

我想知道人们使用什么策略来处理主从设置中的实体的创建和编辑。 (我们的应用是一款支持互联网的桌面应用。)

以下是我们当前的处理方式:在弹出窗口中为需要编辑的实体创建一个表单,我们提供该对象的副本。当用户单击“取消”按钮时,我们关闭窗口并完全忽略该对象。当用户点击“确定”按钮时,通知主视图并接收编辑的实体。然后它使用 originalEntity.copyFrom(modifiedEntity) 将修改实体的属性复制到原始实体中。如果我们想创建一个新实体,我们将一个空实体传递给弹出窗口,然后用户可以编辑它,就好像它是现有实体一样。主视图需要决定是将接收到的实体“插入”还是“更新”到它管理的集合中。

我对上述工作流程有一些疑问和意见:

  • 应该由谁来处理实体副本的创建? (主要或详细)
  • 我们使用 copyFrom() 来防止必须替换集合中的实体,这可能导致引用中断。有一个更好的方法吗? (实现 copyFrom() 可能会很棘手)
  • 新实体接收到 -1 的 id(服务器层/休眠使用它来区分插入或更新)。在保存实体之前按 id 查找(缓存)实体时,这可能会导致问题。我们是否应该为每个新实体使用临时唯一 ID?

任何人都可以分享提示和技巧或经验吗?谢谢!

编辑:我知道这个问题没有绝对错误或正确的答案,所以我只是在寻找人们分享他们处理主要/细节情况的想法和优缺点.

【问题讨论】:

    标签: domain-driven-design desktop entity desktop-application master-detail


    【解决方案1】:

    您可以通过多种方式改变这种方法。请记住,没有解决方案本身真的是“错误的”。这一切都取决于您的具体情况。这是给猫剥皮的一种方法。

    谁应该处理实体副本的创建? (主或细节)

    我将 master 视为持久实体子集的内存列表表示。我会允许主人处理对其列表的任何更改。列表本身可以是自定义集合。使用 ItemChanged 事件向 master 发出通知,告知项目已更新并需要保留。触发 NewItem 事件以通知 master 插入。

    我们使用 copyFrom() 来防止必须替换集合中的实体,这可能导致引用中断。有一个更好的方法吗? (实现 copyFrom() 可能很棘手)

    我不会使用 copyFrom(),而是将现有引用传递给详细信息弹出窗口。如果您使用可枚举集合来存储主列表,则可以将从 list[index] 返回的对象传递到详细信息窗口。引用本身将被更改,因此无需在列表中使用任何类型的 Replace 方法。按下 OK 后,触发 ItemChanged 事件。您甚至可以传递索引,以便它知道要更新哪个对象。

    新实体接收到 -1 的 id(服务器层/休眠使用它来区分插入或更新)。在保存实体之前按 id 查找(缓存)实体时,这可能会导致问题。我们是否应该为每个新实体使用一个临时的唯一 ID?

    更改不会立即持久化吗?使用Hibernate Session with the Unit of Work pattern 来确定要插入什么以及要更新什么。还有更多工作单元的例子。如果 Java 端的内容不多,您可能需要查看 .NET 社区的一些博客文章。无论哪种方式,这个概念都是同一种动物。

    希望这会有所帮助!

    【讨论】:

    • 感谢您的反馈。将引用传递给编辑的问题在于,您不能在不存储实体的原始值的情况下取消或撤消更改。
    • 我想我可能遗漏了一些东西。为了澄清,你是说你的主列表有不同的状态,比如脏/干净?您是否在详细信息窗口中添加和编辑来自主控的项目,在详细信息窗口中单击确定,然后必须使用主控窗口上的某些控件来提交或回滚更改?
    • 您的数据对象是否以某种从您的示例中不明显的方式绑定到表单?我只是想知道你在哪里调用你的 .set 方法。我想我的想法和凯文一样。
    • master 持有一个缓存的持久化实体列表。当用户单击主列表中的项目时,会打开一个弹出窗口,其中包含用户可以编辑的所选项目的详细信息。我们使用所选项目的副本进行编辑,因此我们只需关闭详细信息窗口即可撤消对项目的更改。但是,当我们在详细信息中单击“确定”时,我们会关闭弹出窗口并需要合并更改。更改不会立即保留。主服务器上有一个保存操作,通过(异步)远程调用将所有更改保存在数据库中。工作单元模式在这里可能很有趣。
    【解决方案2】:

    CSLA 库可以帮助解决这种情况。

    但是,如果你想自己实现:

    你有一个主对象,主对象包含一个子对象列表。

    明细表单可以直接编辑子对象。由于一切都是引用类型,所以主对象会自动更新。

    问题在于知道主对象是脏的,因此应该将其持久化到您的数据库或诸如此类。

    CSLA 使用 IsDirty() 属性处理此问题。在主对象中,您将查询每个子对象以查看它是否脏,如果是,则保留所有内容(以及跟踪主对象本身是否脏)

    你也可以处理这个是INotifyPropertyChanged接口。

    至于你的一些其他问题:

    你想分离你的逻辑。实体可以处理其自身属性的存储和自身的完整性规则,但不同对象如何相互交互的逻辑应该是分开的。研究 MVC 或 MVP 等模式。

    在这种情况下,新子对象的创建应该在主对象中,或者应该在创建子对象然后将其添加到父对象的单独业务逻辑对象中。

    对于 ID,使用 GUID 作为 ID 可以为您节省很多问题,因为这样您就不必与数据库对话来确定正确的 ID。您可以在对象上保留一个标志,以判断它是否是新的(因此应该插入或更新)。

    同样,CSLA 会为您处理所有这些,但确实有相当多的开销。

    关于取消时的撤消:CSLA 已实现 n 级撤消,但如果您尝试手动操作,我会使用您的 CopyFrom 函数,或者在取消时从持久层刷新对象的数据(重新获取)。

    【讨论】:

      【解决方案3】:

      我刚刚实现了这样一个模型。但没有使用 NH,我使用自己的代码将对象持久保存在 Oracle Db 中。

      我在同一个 Web 表单中使用了主细节概念。

      就像我有主实体网格一样,在详细操作命令上,我在单击的主记录行下方打开一个惩罚。

      在详细信息添加模式下,我只是填充了一个空实体,其 id 由静态字段以负数生成。在保存详细信息按钮上,我将该实体保存在 Asp.NET 会话中主记录的详细信息列表中。

      在详细信息编辑时,我使用 Jquery 通过 ajax 调用将选定的详细信息填充到详细信息面板中,并在点击的行下方添加了该惩罚。

      在保存按钮上,我将主会话(包含详细信息列表)保存在数据库中。

      我工作得很好,好像大师需要填写多个细节。

      如果您愿意,也可以使用 Jquery Modal 来弹出该面板,而不是在行下方追加。

      希望它有所帮助:) 谢谢,

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-12-27
        • 2014-10-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-08-26
        相关资源
        最近更新 更多