zoukankan      html  css  js  c++  java
  • DevExpress_XAF_根据集合(Collection)计算属性值(例子:产品列表统计订单明细)

      事先声明,本文大部分内容根据官方文件得到,有些翻译不准确的还望见谅。

      什么叫基于集合计算属性值?根据下图我们可以知道。在订单关系中,订单数量(Orders Count)、订单金额总计(Orders Total)、订单最大值 (Maximum Order),由下方列表(在业务类中用集合表示)经过统计获得。

    初始化类的实现(没有统计功能时的源码)

      订单(Order)和产品(Product)关系为多对多。

      产品(Product)源码:

     1 [DefaultClassOptions]
     2 public class Product : BaseObject {
     3     public Product(Session session) : base(session) { }
     4     private string fName;
     5     public string Name {
     6         get { return fName; }
     7         set { SetPropertyValue("Name", ref fName, value); }
     8     }
     9     [Association("Product-Orders"), Aggregated]
    10     public XPCollection<Order> Orders {
    11         get { return GetCollection<Order>("Orders"); }
    12     }
    13 }

       订单源码:

     1 [DefaultClassOptions]
     2 public class Order : BaseObject {
     3     public Order(Session session) : base(session) { }
     4     private string fDescription;
     5     public string Description {
     6          get { return fDescription; }
     7          set { SetPropertyValue("Description", ref fDescription, value); }
     8     }
     9     private decimal fTotal;
    10     public decimal Total {
    11         get { return fTotal; }
    12         set { SetPropertyValue("Total", ref fTotal, value); }
    13     }
    14     private Product fProduct;
    15     [Association("Product-Orders")]
    16     public Product Product {
    17         get { return fProduct; }
    18         set { SetPropertyValue("Product", ref fProduct, value); }
    19     }
    20 }

    计算属性

      下面的代码片段演示了三个计算属性的实现——订单数量(Orders Count)、订单金额总计(Orders Total)、订单最大值 (Maximum Order)

     1 [DefaultClassOptions]
     2 public class Product : BaseObject {
     3     // ... 
     4     private int? fOrdersCount = null;
     5     public int? OrdersCount {
     6         get {
     7             if(!IsLoading && !IsSaving && fOrdersCount == null)
     8                 UpdateOrdersCount(false);
     9             return fOrdersCount;
    10         }
    11     }
    12     private decimal? fOrdersTotal = null;
    13     public decimal? OrdersTotal {
    14         get {
    15            if(!IsLoading && !IsSaving && fOrdersTotal == null)
    16                 UpdateOrdersTotal(false);
    17             return fOrdersTotal;
    18         }
    19     }
    20     private decimal? fMaximumOrder = null;
    21     public decimal? MaximumOrder {
    22         get {
    23             if(!IsLoading && !IsSaving && fMaximumOrder == null)
    24                 UpdateMaximumOrder(false);
    25             return fMaximumOrder;
    26         }
    27     }
    28 }

       以下方法是三个计算属性值具体方法。

     1 [DefaultClassOptions]
     2 public class Product : BaseObject {
     3     // ... 
     4     public void UpdateOrdersCount(bool forceChangeEvents) {
     5         int? oldOrdersCount = fOrdersCount;
     6         fOrdersCount = Convert.ToInt32(Evaluate(CriteriaOperator.Parse("Orders.Count")));
     7         if (forceChangeEvents)
     8           OnChanged("OrdersCount", oldOrdersCount, fOrdersCount);
     9     }
    10     public void UpdateOrdersTotal(bool forceChangeEvents) {
    11         decimal? oldOrdersTotal = fOrdersTotal;
    12         decimal tempTotal = 0m;
    13         foreach (Order detail in Orders)
    14             tempTotal += detail.Total;
    15         fOrdersTotal = tempTotal;
    16         if (forceChangeEvents)
    17             OnChanged("OrdersTotal", oldOrdersTotal, fOrdersTotal);
    18     }
    19     public void UpdateMaximumOrder(bool forceChangeEvents) {
    20         decimal? oldMaximumOrder = fMaximumOrder;
    21         decimal tempMaximum = 0m;
    22         foreach (Order detail in Orders)
    23             if (detail.Total > tempMaximum)
    24                 tempMaximum = detail.Total;
    25         fMaximumOrder = tempMaximum;
    26         if (forceChangeEvents)
    27             OnChanged("MaximumOrder", oldMaximumOrder, fMaximumOrder);
    28     }
    29 }

       注意,fOrdersCount是在客户端使用UpdateOrdersCount方法中从内部XPO缓存加载的对象来计算的。可以使用下面的代码在服务器端计算fOrdersCount,这样就不会考虑未提交的对象。

    1 fOrdersCount = Convert.ToInt32(Session.Evaluate<Product>(CriteriaOperator.Parse("Orders.Count"), 
    2     CriteriaOperator.Parse("Oid=?", Oid)));

      在Order类的TotalProduct属性设置器中,当Order对象的属性值发生变化且对象当前没有初始化时,UI将被更新:

     1 [DefaultClassOptions]
     2 public class Order : BaseObject {
     3     // ... 
     4     private decimal fTotal;
     5     public decimal Total {
     6         get { return fTotal; }
     7         set {
     8             bool modified = SetPropertyValue("Total", ref fTotal, value);
     9             if(!IsLoading && !IsSaving && Product != null && modified) {
    10                 Product.UpdateOrdersTotal(true);
    11                 Product.UpdateMaximumOrder(true);
    12             }
    13         }
    14     }
    15     private Product fProduct;
    16     [Association("Product-Orders")]
    17     public Product Product {
    18         get { return fProduct; }
    19         set {
    20             Product oldProduct = fProduct;
    21             bool modified = SetPropertyValue("Product", ref fProduct, value);
    22             if(!IsLoading && !IsSaving && oldProduct != fProduct && modified) {
    23                 oldProduct = oldProduct ?? fProduct;
    24                 oldProduct.UpdateOrdersCount(true);
    25                 oldProduct.UpdateOrdersTotal(true);
    26                 oldProduct.UpdateMaximumOrder(true);
    27             }
    28         }
    29     }
    30 }

       在Product类中,OnLoaded方法被覆盖,因为在使用延迟计算时需要重置缓存的值。

     1 [DefaultClassOptions]
     2 public class Product : BaseObject {
     3     // ... 
     4     protected override void OnLoaded() {
     5         Reset();
     6         base.OnLoaded();
     7     }
     8     private void Reset() {
     9         fOrdersCount = null;
    10         fOrdersTotal = null;
    11         fMaximumOrder = null;
    12     }
    13     // ...

     将计算的值属性存储到数据库中

    非持久性属性值时影响性能的。为了避免这个问题,可以将计算值存储到数据库中。可以使用PersistentAttribute将值保存到数据库中。

     1 [DefaultClassOptions]
     2 public class Product : BaseObject {
     3     // ... 
     4     [Persistent("OrdersCount")]
     5     private int? fOrdersCount = null;
     6     [PersistentAlias("fOrdersCount")]
     7     public int? OrdersCount {
     8         // ... 
     9     }
    10     [Persistent("OrdersTotal")]
    11     private decimal? fOrdersTotal = null;
    12     [PersistentAlias("fOrdersTotal")]
    13     public decimal? OrdersTotal {
    14         // ... 
    15     }
    16     [Persistent("MaximumOrder")]
    17     private decimal? fMaximumOrder = null;
    18     [PersistentAlias("fMaximumOrder")]
    19     public decimal? MaximumOrder {
    20         // ... 
    21     }
    22     // ...

     从主订单类中移除OnLoaded方法重载。

    参考文献

      [1] https://documentation.devexpress.com/eXpressAppFramework/113179/Task-Based-Help/Business-Model-Design/eXpress-Persistent-Objects-XPO/How-to-Calculate-a-Property-Value-Based-on-Values-from-a-Detail-Collection

      [2]官网项目源码及示例网址:https://www.devexpress.com/Support/Center/Example/Details/E305/how-to-calculate-a-master-property-based-on-values-from-a-details-collection

  • 相关阅读:
    使用线程新建WPF窗体(公用进度条窗体)
    WPF--模板选择
    WPF命令(Command)介绍、命令和数据绑定集成应用
    WPF 员工卡条形码
    WPF入门教程系列(二) 深入剖析WPF Binding的使用方法
    R语言——实验5-聚类分析
    R语言——实验5-聚类分析
    Java学习---流与文件
    Java学习---流与文件
    Java学习---异常处理
  • 原文地址:https://www.cnblogs.com/luyj00436/p/11475202.html
Copyright © 2011-2022 走看看