网站导航网学 原创论文 原创专题 网站设计 最新系统 原创论文 论文降重 发表论文 论文发表 UI设计定制 论文答辩PPT格式排版 期刊发表 论文专题
返回网学首页
网学原创论文
最新论文 推荐专题 热门论文 论文专题
当前位置: 网学 > 设计资源 > .Net编程 > 正文

实战剖析三层架构(三)不要说BLL没有用

论文降重修改服务、格式排版等 获取论文 论文降重及排版 论文发表 相关服务

在本系列的第一篇中,笨熊已经介绍过BLL层的功用,也说明了为什么许多人觉得这一层可有可无。但看近期博客园的文章,还有不少朋友对BLL的存在仍有疑问。正好今天碰到的这个问题颇具代表性,写出来让这些朋友对BLL在业务系统中的功用有个具体的感觉。

    先简要介绍一下要做的功能,在程序中,用户输入商品的商品编码,系统从数据库中提取显示此商品的详细信息(图1)。如果一个商品有多个供应商,则弹出提示框供用户选择某一供应商(图2)。

    图1

    图2

功能上来说很简单,先定义一个实体类:

  1. public class StockTakingCardInfo 
  2.  { 
  3.      private string _GoodBarcode; 
  4.      private string _GoodBarcodeType; 
  5.      private string _GoodCode; 
  6.      private string _GoodName; 
  7.      private string _Standard; 
  8.      private string _Unit; 
  9.      private decimal _SellPrice; 
  10.      private string _CargoGroup; 
  11.      private string _CargoGroupName; 
  12.      private string _Distribution; 
  13.      private string _DistributionName; 
  14.      private string _ProducingArea; 
  15.  
  16.      public string GoodBarcode 
  17.      { 
  18.          get { return _GoodBarcode; } 
  19.          set { _GoodBarcode = value; } 
  20.      } 
  21.  
  22.      public string GoodBarcodeType 
  23.      { 
  24.          get { return _GoodBarcodeType; } 
  25.          set { _GoodBarcodeType = value; } 
  26.      } 
  27.  
  28.      public string GoodCode 
  29.      { 
  30.          get { return _GoodCode; } 
  31.          set { _GoodCode = value; } 
  32.      } 
  33.  
  34.      public string GoodName 
  35.      { 
  36.          get { return _GoodName; } 
  37.          set { _GoodName = value; } 
  38.      } 
  39.  
  40.      public string Standard 
  41.      { 
  42.          get { return _Standard; } 
  43.          set { _Standard = value; } 
  44.      } 
  45.  
  46.      public string Unit 
  47.      { 
  48.          get { return _Unit; } 
  49.          set { _Unit = value; } 
  50.      } 
  51.  
  52.      public decimal SellPrice 
  53.      { 
  54.          get { return _SellPrice; } 
  55.          set { _SellPrice = value; } 
  56.      } 
  57.  
  58.      public string CargoGroup 
  59.      { 
  60.          get { return _CargoGroup; } 
  61.          set { _CargoGroup = value; } 
  62.      } 
  63.  
  64.      public string CargoGroupName 
  65.      { 
  66.          get { return _CargoGroupName; } 
  67.          set { _CargoGroupName = value; } 
  68.      } 
  69.  
  70.      public string Distribution 
  71.      { 
  72.          get { return _Distribution; } 
  73.          set { _Distribution = value; } 
  74.      } 
  75.  
  76.      public string DistributionName 
  77.      { 
  78.          get { return _DistributionName; } 
  79.          set { _DistributionName = value; } 
  80.      } 
  81.  
  82.      public string ProducingArea 
  83.      { 
  84.          get { return _ProducingArea; } 
  85.          set { _ProducingArea = value; } 
  86.      } 
  87.  } 

然后数据层负责提取数据:  

  1. public IList<StockTakingCardInfo> GetStockTakingCards(string code)     
  2.      /***** 从数据库中提取 *****/ 
  3.      string goodCode; 
  4.  
  5.      CmdCommand cmd = new CmdCommand(); 
  6.      cmd.CommandText = "SELECT DPTM FROM commod_xstm1 WHERE xstm = '" + code + "'"
  7.      OleDbDataReader drXstm = cmd.ExecuteReader(); 
  8.      if (drXstm.HasRows) 
  9.      {   //输入的是销售条码 
  10.           drXstm.Read(); 
  11.          goodCode = drXstm["DPTM"].ToString(); 
  12.          drXstm.Close(); 
  13.      } 
  14.      else 
  15.      {   //输入的是货号 
  16.           goodCode = code; 
  17.      } 
  18.      cmd.Disconnection(); 
  19.  
  20.      cmd.CommandText = ""
  21.      OleDbDataReader dr = cmd.ExecuteReader(); 
  22.  
  23.      IList<StockTakingCardInfo> stockTakingCards = new List<StockTakingCardInfo>(); 
  24.      if (dr.HasRows) 
  25.      {   // 
  26.          while (dr.Read()) 
  27.          { 
  28.              StockTakingCardInfo stockTakingCard = new StockTakingCardInfo(); 
  29.              stockTakingCard.GoodBarcode = dr["销售条码"].ToString(); 
  30.              stockTakingCard.GoodBarcodeType = dr["销售条码类型"].ToString(); 
  31.              stockTakingCard.GoodCode = dr["商品编码"].ToString(); 
  32.              stockTakingCard.GoodName = dr["商品名称"].ToString(); 
  33.              stockTakingCard.Standard = dr["规格"].ToString(); 
  34.              stockTakingCard.Unit = dr["单位"].ToString(); 
  35.              stockTakingCard.SellPrice = Convert.ToDecimal(dr["零售价"]); 
  36.              stockTakingCard.CargoGroup = dr["柜组"].ToString(); ; 
  37.              stockTakingCard.CargoGroupName = dr["柜组名称"].ToString(); 
  38.              stockTakingCard.Distribution = dr["供货商"].ToString(); 
  39.              stockTakingCard.DistributionName = dr["供货商名称"].ToString(); 
  40.              stockTakingCard.ProducingArea = dr["产地"].ToString(); 
  41.              stockTakingCards.Add(stockTakingCard); 
  42.           } 
  43.           dr.Close(); 
  44.           cmd.Disconnection(); 
  45.     } 
  46.     return stockTakingardings 

逻辑层没什么用,直接调用DAL的方法得到数据并返回。

    表现层(这里是WinForm窗体)调用逻辑层方法得到数据,并判断数据条目,如果是一条,则直接显示;如果是多条,则弹出提示框让用户选择,选好后再显示(代码略)。

    编写好后运行,代码没有问题,但是在批量测试时发现了几种特殊情况。

    1、一些商品没有提供条码(如蔬菜、水果等散装商品),因此需要根据商品编号生成条码。
    2、一些商品除了本身的条码外,在商品的包装箱上还有条码(比如啤酒、露露、牛奶等,瓶上的条码和箱上的条码是不一样的。因此买一箱时只需扫描包装箱上的条码即可,而不用拆箱扫描里面的商品)。
    3、一些商品只有外包装箱上有条码,商品本身却没有条码,但在销售时还需要拆开来按单个商品销售,这时也要根据商品编码生成条形码。
    考虑这三种情况,那么从数据库中查询时,返回的结果有以下几种(按条码、条码类型、编码、名称、供应商显示,其它列略。条码类型列,A表示条码为商品本身条码,B表示条码为包装箱条码)。

    (1)一般情况(结果返回1 - n条数据)
    692590758024,A,186202,舒尔但莫代尔女单衣,唐山XX有限公司
    (2)商品本身没有条码(结果返回1 - n条数据)
    NULL,NULL,80604,散大米,唐山XX有限公司
    NULL,NULL,80604,散大米,天津市XX加工厂
    (3)商品本身有条码,包装箱还有条码(结果返回n条数据)
    690180818886,A,104992,露露,河北XX股份有限公司
    690180818882,B,104991,露露,河北XX股份有限公司
    690180818886,A,104991,露露,锦江XX有限公司
    690180818882,B,104991,露露,锦江XX有限公司
    (4)商品本身无条码,包装箱有条码(结果返回1 - n条数据)
    692590751824,B,101974,双汇王中王,唐山XX有限公司
    692590751824,B,101974,双汇王中王,河北XX有限公司

    这样汇总整理一下,对于重数据库中查询返回的结果,要做如下处理:首先判断条码是否为空,如果空则生成条码。确认条码不为空后,判断条码类型中是否全是B。如果有A有B,则进行筛选,保留类型为A的条目。如果全是B,则将结果中的条码全部用自动生成条码替换。

    确定了处理过程以后,决定需要将此过程放在何处。首先考虑的是数据层,如果能直接提取出所需结果那是最好的,但是有几点原因决定了不能放在数据层:

    (1)数据层的这个方法提供的数据具有通用性,逻辑层中不光一个方法对其进行调用,更改了返回结果会造成逻辑层的其它方法无法使用此结果。

    (2)这个方法的查询语句非常简单,如果增加了此过程,则SQL语句的编写难度会加大,而且很难用1条语句处理这几种情况,必须实现的话,则此方法的SQL查询语句需要改为3句,还要提前执行一条SQL判断语句来决定使用那个SQL查询语句。成倍增加了编写难度与执行时间。

    所以数据层不是进行处理的好地方。

再看看表示层,如果放在了表示层,则需要在主窗口(图1)进行判断,对数据进行处理,这样将逻辑处理代码与显示代码混合在一起,不但乱,而且加大了编码量,因为每个逻辑分值里面都要编写相应的显示代码。所以放在表示层也不是个好主意(呵呵,一开始感觉简单,真的想不建逻辑层直接合并在表示层中着)。

因此,最适合放置此处理过程的地方,就是业务逻辑层了。而且此处的工作就是业务逻辑的处理,即使没有上述问题,也应该放与此层。 

  1. public IList<StockTakingCardInfo> GetStockTakingCards(string code) 
  2. {       
  3.       IList<StockTakingCardInfo> stockTakingCards = DAL.GetStockTakingCards() 
  4.  
  5.       /***** 业务逻辑整理(还未编写空白条码处理部分) *****/ 
  6.       //判断是否有A码 
  7.        bool hasA = false
  8.       foreach (StockTakingCardInfo myStockTakingCard in stockTakingCards) 
  9.       { 
  10.           if (myStockTakingCard.GoodBarcodeType == "A"
  11.           { 
  12.                 hasA = true
  13.                 break
  14.           } 
  15.       } 
  16.  
  17.       //根据是否有A吗处理 
  18.        IList<StockTakingCardInfo> reStockTakingCards = new List<StockTakingCardInfo>(); 
  19.       if (hasA) 
  20.       {   // 
  21.           foreach (StockTakingCardInfo reStockTakingCard in stockTakingCards) 
  22.           { 
  23.                 if (reStockTakingCard.GoodBarcodeType == "A"
  24.                 { 
  25.                     reStockTakingCards.Add(reStockTakingCard); 
  26.                 } 
  27.           } 
  28.        } 
  29.        else 
  30.        {   //没有A码 
  31.              //将所有的销售条码重新生成 
  32.              foreach (StockTakingCardInfo reStockTaking in stockTakingCards) 
  33.             { 
  34.                 if (reStockTaking.GoodCode.Length == 5) 
  35.                 { 
  36.                     reStockTaking.GoodBarcode = "2000000" + reStockTaking.GoodCode; 
  37.                 } 
  38.                 else if (reStockTaking.GoodCode.Length == 6) 
  39.                 { 
  40.                     reStockTaking.GoodBarcode = "200000" + reStockTaking.GoodCode; 
  41.                 } 
  42.                 reStockTakingCards.Add(reStockTaking); 
  43.             } 
  44.         } 
  45.  
  46.         /***** 返回处理后结果 ******/ 
  47.         return reStockTakingCards; 
设为首页 | 加入收藏 | 网学首页 | 原创论文 | 计算机原创
版权所有 网学网 [Myeducs.cn] 您电脑的分辨率是 像素
Copyright 2008-2020 myeducs.Cn www.myeducs.Cn All Rights Reserved 湘ICP备09003080号 常年法律顾问:王律师