【问题标题】:DataTable Wrapper or How to decouple UI from Business logicDataTable Wrapper 或如何将 UI 与业务逻辑分离
【发布时间】:2010-10-15 18:38:24
【问题描述】:

我正在使用网络表单、C#、Asp.net。 众所周知,在这个模型中,UI和业务逻辑经常混在一起,如何有效的将它们分开?

我想使用的示例是: 我有一个 GridView 和一个 DataTable(GridView 绑定到 DataTable 并且 DataTable 是从存储过程提供的)。

我希望将 GridView (UI) 和 DataTable(业务逻辑)解耦。

是否值得为 DataTable 编写一个包装器?是否有经过验证和测试的实用模式可供您推荐遵循?

如果有经验的人能提供一些启示,那就太棒了。 最后,我想说 ASP MVC 现在不是一个选项,所以不推荐它。

我的数据库访问层返回一个 DataTable。 请注意,我必须使用此数据库层,因为这是公司政策。

【问题讨论】:

    标签: asp.net gridview webforms datatable decoupling


    【解决方案1】:

    我最近经历了这个,同时将很多相同的东西与我们的 UI 层解耦。

    你可以看到我的进度herehere

    在我看来,A DataTable 确实代表业务逻辑。具体来说,它是直接从数据库中提取的数据。业务逻辑将这些数据转化为真正有用的业务对象。

    因此,第一步是将 DataTable 与 Business 对象分离。

    您可以通过创建对象和List<object> 来做到这一点,这些对象和List<object> 构成数据表和数据表的集合,然后您可以创建一个显示这些对象的 ListView。我在上面发布的链接中介绍了后面的步骤。前面的步骤如下所示:

    1. 创建一个代表您的对象的类。
    2. 遍历您的 DataTable(或 DataSet,或者您检索数据)并将这些字段推送到该对象(或 List<T>)的属性中;
    3. 将该列表返回到 Gridview 或 ListView 以显示。

    这样,您的 ListView 或 Gridview 不会与您检索数据的方法紧密耦合。如果您决定稍后从 JSON 查询或 XML 文件中获取数据,会发生什么?然后你必须将它构建到那里。

    第 1 步 - 从数据库中获取数据

    有多种方法可以从数据库中获取数据,我无法在此处一一介绍。我假设您已经知道如何从数据库中检索数据,如果您不知道,则可以使用 quite a few links。假设您已连接到数据库,并使用SQLDataReader 检索数据。我们去那里接。

    类图

    Foo
    ----
    id
    Name
    Description
    

    方法如下:

     private void FillDefault(SqlDataReader reader, Foos foo)
            {
                try
                {
                    foo.id = Convert.ToInt32(reader[Foo.Properties.ID]);
                    foo.Name = reader[Foo.Properties.NAME].ToString();
                        
                    
                 if (!string.IsNullOrEmpty(
                    reader[Foo.Properties.DESCRIPTION].ToString()))
                     foo.Description = 
                     reader[Foo.Properties.DESCRIPTION].ToString();
                 else foo.Description = string.Empty;
                }
                catch (Exception ex)
                {
                   throw new Exception(
                   string.Format("Invalid Query. 
                   Column '{0}' does not exist in SqlDataReader.", 
                   ex.Message));
                }
            }
    

    一旦发生这种情况,您可以通过在以SQLDataReader.Read() 函数为目标的while 循环中执行该过程来返回一个列表。

    一旦你这样做了,让我们假设你返回的Foo 是一个列表。如果你这样做,并按照我上面给出的第一个链接,你可以用List<T> 替换Dictionary<TKey, TValue> 并获得相同的结果(略有不同)。 Properties 类只包含数据库中的列名,因此您可以在一个地方更改它们(以防万一)。

    DataTable - 根据评论更新

    您始终可以插入中间对象。在本例中,我将在 DataTable 和 UI 之间插入一个业务层,并且我已经在上面讨论了我要做什么。但是 DataTable 不是业务对象;它是数据库的可视化表示。您不能将其传输到 UI 层并将其称为解耦。他们说您必须使用 DataTable,他们是否说您必须将该 DataTable 传输到 UI?我无法想象他们会。如果你这样做了,那么你将永远不会解耦。在 DataTable 和 UI 层之间总是需要一个中间对象。

    【讨论】:

    • 我无法访问您的链接。这可能是因为您的情况是流程的特定部分,而对我来说这是第一次,我想从头开始,而不是从字典开始。
    • 好的;很公平。如果你愿意,我可以扩展我的答案。
    • 我要纠正自己。我必须使用 DataTable 对象,因为这是我的数据层返回的,这是公司政策——我们都必须使用这个数据访问类。那我该如何解耦呢?
    • 谢谢,嗯,在我的情况下,我想我必须将 DataTable 转换为 List。在这一点上,我将不得不问,将为 GridView 制作的对象转换为通用 List 有什么好处?
    • 我认为在我的场景中创建一个继承自 DataTable 的类更适用。然后,我可以将其作为对 UI 事件的响应进行操作。实际上,也许不是——这几乎就是我现在正在做的事情。鉴于我有使用 DataTable 的限制,我不确定是否值得解耦。
    【解决方案2】:

    考虑实现 MVP(模型视图展示器)模式。它通过演示者界面为您提供了商业逻辑的分离,这也允许更好的单元测试能力。然后,您的 aspx 页面代码隐藏只是事件的连接器和属性的 getter/setter。您可以在 MS 模式和实践企业应用程序块(CAB - 复合应用程序块 - 如果我没记错的话)中找到它。
    您可以在此处阅读更多信息:http://msdn.microsoft.com/en-us/magazine/cc188690.aspx
    但从 DataTable/DataSets 到对象 (POCO) 也是首选。

    【讨论】:

      【解决方案3】:

      我首先将数据表解耦到垃圾桶中。构建一个领域层,然后是某种类型的处理数据库的数据访问层(推荐使用 ORM)。

      然后构建一个向 UI 提供数据的服务层。所有业务逻辑都应该在服务或实体本身内。

      【讨论】:

      • 别找我了。我必须使用 DataTable 对象,因为这是我的数据层返回的,这是公司政策 - 我们都必须使用这个数据访问类。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-15
      • 1970-01-01
      • 2018-08-28
      • 2011-04-10
      • 1970-01-01
      相关资源
      最近更新 更多