【问题标题】:C# CSLA business object dilemma: read-only vs read/writeC# CSLA 业务对象困境:只读 vs 读/写
【发布时间】:2009-08-14 15:59:31
【问题描述】:

我是一个团队的一员,负责将我们旧的 VB6 UI/COBOL 数据库应用程序改造成现代。在我被录用之前,我决定(主要是关于销售,我敢肯定)在数据库之前重做 UI。所以,现在我们使用 WPF 和 MVVM 取得了很好的效果,到目前为止效果非常好,尤其是使用 CSLA 作为我们的模型层。

但是,由于我们的开发与旧产品的下一个版本并行进行,因此我们受到了一些限制。我们无法对对 COBOL 数据库的调用进行任何更改(或最小更改)。到目前为止,这一切都很好,尽管如果您相信的话,可以追溯到 SQL Server 的辉煌岁月。

关于我们的 BO 设计,我遇到了一个特别令人讨厌的障碍,那就是处理列表中返回的“轻量级”业务对象及其“完整”对应项。让我试着构造一个例子:

假设我们在数据库中有一个带有一堆字段的人员对象。当我们对该表进行搜索时,我们不会返回所有字段,因此我们用这些填充我们的 lite 对象。这些字段可能是也可能不是完整人员的子集。我们可能已经进行了一两次连接以检索特定于搜索的其他一些信息。但是,如果我们想编辑我们的 person 对象,我们必须再次调用以获取完整版本来填充 UI。这给我们留下了两个对象,并试图在 1 个 VM 中处理它们的状态,同时试图在删除、编辑和添加之后保持人员列表在它所在的任何父对象上保持同步。最初,我让我们的 lite person 对象派生自 ReadOnlyBase。但是现在我正在处理与完整 BO 列表相同的列表行为,除了半满,半精简版,我想我应该让精简版和完整版都来自 BusinessBase 并简单地将 lite 版本的 setter 属性设为私有。

有没有其他人遇到过并找到解决方案?睡在上面之后,我想出了这个潜在的解决方案。如果我们将完整版和精简版 BO 包装在另一个 BO 中会怎样,如下所示:

public class PersonFull : BusinessBase<PersonFull>
{
  ...
}
public class PersonLite : BusinessBase<PersonLite>
{
  ...
}

public class Person : BusinessBase<Person>
{
  public PersonFull PersonFull;
  public PersonLite PersonLite;
}
public class PersonList : BusinessListBase<PersonList, Person>
{
}

显然,所有内容都是 CSLA 注册属性等,但为了简洁起见,它们是那里的字段。在这种情况下, Person 和 PersonList 将包含所有工厂方法。在搜索操作之后,PersonList 将由 PersonLite 成员全部填充且 PersonFull 对象全部为空的 Person 对象填充。如果我们需要获得完整版本,我们只需告诉 Person 对象这样做,现在我们有了 PersonFull 对象,因此我们可以填充编辑 UI。如果要删除 Person 对象,我们可以使用适当的 CSLA 删​​除程序轻松地执行此操作,同时仍然在所有正在侦听它的 VM 中保持列表的完整性。

所以,我希望这对每个人都有意义,如果有人有不同的解决方案,他们一定会成功采用或批评这个解决方案!

谢谢!

(转自:http://forums.lhotka.net/forums/thread/35576.aspx

【问题讨论】:

    标签: c# business-objects csla readonly read-write


    【解决方案1】:
    public class PersonLite : ReadOnlyBase<PersonLite>
    {
        public void Update(PersonFull person) { }
    }
    
    public class PersonFull : BusinessBase<PersonFull>
    {
        // blah blah
    }
    

    我将使用对“完整”对象所做的更改来更新“精简”对象,并将其保留为ReadOnlyBase。重要的是要记住ReadOnlyBase 中的“ReadOnly”是指仅从数据库中读取的对象,而不会保存到其中。一个不太优雅但更准确的名称是NotSavableBase,因为这样的对象除了获取之外没有DataPortal_XYZ 机制。出于显而易见的原因,此类对象通常具有不可变的属性,但它们并非必须如此。 ReadOnlyBase 派生自 Core.BindableBase 并实现 INotifyPropertyChanged,因此更改其属性的值可以很好地用于绑定。

    当您保存“完整”对象时,将新保存的实例传递给列表中实例的Update(PersonFull) 方法,并从“完整”对象更新“精简”对象的属性。

    我已经多次使用这种技术,效果很好。

    【讨论】:

      【解决方案2】:

      如果您查看 Rocky 随 CSLA 框架提供的示例,您会注意到他总是将只读对象与读/写对象分开。我认为这样做是有充分理由的,因为行为将完全不同。只读对象将更多地基于性能,它们的验证将非常不同,并且通常具有更少的信息。读/写对象不会基于性能,并且严重依赖验证、授权等。

      但是,这让您陷入了当前的困境。我要做的是重载每个类的构造函数,这样您就可以在彼此之间传递它们并从彼此“复制”您需要的东西。

      类似这样的:

      public class PersonLite : BusinessBase<PersonLite>
      {
          public PersonLite(PersonFull fullPerson)
          {
              //copy from fullPerson's properties or whatever
          }
      }
      
      public class PersonFull : BusinessBase<PersonFull>
      {
          public PersonFull(PersonLite litePerson)
          {
              //copy from litePerson's properties or whatever
          }
      }
      

      您也可以使用工厂模式来做到这一点,我相信这是 Rocky 的偏好。

      【讨论】:

      • 我不完全确定你的提议应该解决什么问题。精简版 BO 永远不会填充完整版 BO,因为我们可以去数据库中使用精简版中的唯一数据来补充完整版 BO。我想我可以在编辑后看到完整版本更新精简版,但这并不是真正的方法。
      • 精简版无法完全填充完整版,但它可能足以显示给用户,其余数据可以延迟加载。我过去曾这样做并取得了一些成功。如果您尝试修改内存对象,那么您的处理方法将完全不同。
      • 如果打算在前端完成后重建后端 BO,为什么不将此作为测试用例,从包含所有属性的新 CSLA 对象开始?
      • 好问题。目前,我们的 BO 直接映射到 COBOL 中的文件记录布局,我将属性放在属性上,以便帮助类知道如何解析来自 COBOL 的输入并填充属性。这就是为什么我们有 2 个不同的对象,因为我们有 2 个来自数据库的不同记录布局。而且这种开发与前端开发同时发生。
      • 这不是 Csla 的工作方式,您也不会以这种方式解决问题。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-09-26
      • 1970-01-01
      • 2021-06-07
      • 1970-01-01
      • 2013-06-06
      • 2018-09-10
      相关资源
      最近更新 更多