【问题标题】:Class properties concerning List<T> requests – Class design dilemma与 List<T> 请求有关的类属性——类设计困境
【发布时间】:2009-06-10 21:38:05
【问题描述】:

当我需要从表(数据库)中获取多条记录时,我的方法会填充特定类的列表(我的所有数据访问层方法都使用列表来表示基于集合的选择语句。我不使用数据表/数据集或xmlDocument 方法)。所以让我们假设下一个简化的场景;我有两个类——客户和订单,这些字段/属性:

Class Customer{
   int IDCustomer
   string CustomerName
   string CustomerAddress
   string CustomerCity
}

Class Order{
   int IDOrder
   int IDCustomer
   string SalePersonName
   decimal OrderSubTotal
   datetime OrderDateCreated
}

所以,假设我们需要一个方法,将所有来自的数据传递到 UI (ObjectDataSource) 来自 Customer 类的 Order Class 属性 + CustomerName 和 CustomerCity。 我希望我的 Order 类方法看起来像:

public List<Order> SelectAll(){ 
}

那么我应该使用哪种方法来完成此任务?如何设置订单类,使其包含关于最佳实践、面向对象范式、性能等的两个额外属性(CustomerName 和 CustomerCity):

方法 A:


Class Order{
   int IDOrder
   int IDCustomer
   string SalePersonName
   decimal OrderSubTotal
   datetime OrderDateCreated
   //--- plus two extra properties of type string
   string CustomerName
   string CustomerCity
}

方法 B:


Class Order{
   int IDOrder
   int IDCustomer
   string SalePersonName
   decimal OrderSubTotal
   datetime OrderDateCreated
   //--- plus extra property of type Customer
   Customer _Customer
}

方法 C:


???

我在 .NET 2.0 上。

【问题讨论】:

    标签: c# .net oop generic-list


    【解决方案1】:

    我可以毫无问题地创建另一个类来展平充当视图模型的查询。

    【讨论】:

      【解决方案2】:

      这听起来像是ORM 的工作。

      【讨论】:

        【解决方案3】:

        毫无疑问,B。客户和订单之间存在一对多的关系 - 一个客户有很多订单(订单列表),一个订单有一个客户(客户类型的标量属性)。

        public class Customer
        {
           public Int32 Id { get; private set; }
           public String Name { get; private set; }
           public String Address { get; private set; }
           public String City { get; private set; }
        
           public IList<Order> Orders { get { return this.orders; } }
           private readonly IList<Orders> orders = new List<Orders>();
        }
        
        Class Order
        {
           public Int32 Id { get; private set; }
           public String SalesPersonName { get; private set; }
           public Decimal SubTotal { get; private set; }
        
           public Customer Customer { get; private set; }
        }
        

        对于用户界面,您可以创建一个单独的类来包装订单,如下所示。

        public class OrderView
        {
            private readonly Order order;
        
            public OrderView(Order order)
            {
                this.order = order;
            }
        
            public Decimal SubTotal { get { return this.order.SubTotal; } }
            public String CustomerCity { get { return this.order.Customer.City; } }
            // ...
        }
        

        【讨论】:

        • 违反得墨忒耳法则,如果你在乎这类事情的话。
        • 我不太喜欢得墨忒耳法则……下面的真的会更好吗?真的不一样吗?客户客户 = this.order.Customer;返回(客户!= null)?客户.城市:字符串.空;我也不喜欢用 GetCustomerFoo() 方法弄乱 Order 类。
        • 我很困惑...您说选项 B,但随后您编造了一个不同的选项来回答问题。在他的方法 B 中,他有一个包含客户的订单。你有它相反的方式,你创建了第三个类。并不是说这是一个糟糕的解决方案,但它并不是你描述的那样接近 B。
        • 你是对的 - 可能有点混乱。选项 B 指的是业务实体(前两个类),我在关系的两端添加了一个客户到订单和一个订单列表到客户。如果无法将数据绑定到嵌套属性,则某些视图需要第三类。它是选项 C 并包装了一个业务实体。
        【解决方案4】:

        如果您允许存在一对多客户与订单的关系,则具有订单列表的客户类将遵循。虽然这与您的原始请求略有不同,但您可能会更轻松地操纵客户及其包含的订单,而不是从父级复制成员。

        Class Customer{
           int IDCustomer
           string CustomerName
           string CustomerAddress
           string CustomerCity
           List<Order> orders;
        
           public List<Order> SelectAll(){ return orders; }
        }
        
        Class Order{
           int IDOrder
           //int IDCustomer -not necessary as parent contains this info
           string SalePersonName
           decimal OrderSubTotal
           datetime OrderDateCreated
        }
        

        【讨论】:

          【解决方案5】:

          因为这是一个设计问题,我认为需要更多信息才能给出完整答案,因为我认为这取决于具体情况。

          如果您已经加载了 Order 对象和 Customer 对象并将它们用于表示层中的不同事物,那么创建一个专门的类来展平显示数据是一个很好的解决方案。

          如果您正在加载信息以显示订单列表并需要每个订单的客户信息,那么我不得不问为什么您不只是创建一个包含相关字段的 CustomerOrder 类并加载首先是因为您无论如何都不会使用客户的额外数据。

          所有这些设计决策都取决于外部因素。最后,我想说正确的设计决策通常是满足您需求的最简单的决策。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-05-09
            • 1970-01-01
            • 1970-01-01
            • 2012-04-20
            相关资源
            最近更新 更多