好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

Ajax服务端框架的综合示例

Ajax服务端框架的综合示例

通用数据访问层及Ajax服务端框架的综合示例,展示与下载

阅读目录

开始 第一部分,界面截图 调用数据访问层的代码 Ajax演示代码 组件性能测试 用户手册,API文档

本文将专门介绍:我的 通用数据访问层  及  Ajax服务端框架 的综合示例,同时也是为了让大家能对这二个组件有更多的了解。 因此,本文将以界面截图以及部分代码展示的方式来说明,这样可能会有更感性的认识它。

这个演示网站的特点:
1. 数据访问全使用了我的通用数据访问层 + 存储过程的实现。
2. 页面使用了大量的Ajax技术,没有任何的直接提交或回传(Submit Form or postback),分页,查询,对话框,都以Ajax的方式实现。
3. 所有Ajax技术的客户端全部基于JQuery,服务端则使用我的Ajax服务端框架
4. 客户端UI使用JQuery Easy-UI
5.  虽然没有使用Asp.net MVC框架,但却使用了MVC思想。

通用数据访问层  及  Ajax服务端框架  的技术特性:

数据访问层设计目标 调用存储过程,不管输入参数多么复杂,不管有多少输出参数,包含转换一个结果集到实体列表,只需要一行C#代码。 Ajax框架的特色 服务端中的C#方法或用户控件对于JS来说是透明的,就好像可以直接访问一下。 Ajax框架的作用意义 接受JS的请求,去调用C#方法或者用户控件。
至于如何调用方法,如何给方法的参数赋值,最后如何处理返回值给客户端,就属于框架本身的事情了。
所有的这一切,对于客户端来说,更是透明的。这些透明的实现也就是框架的意义了。

这个演示网站的业务原型来自于Northwind,但所有的表都是我重新根据示例需要而重新定义的, 数据来源于以前从网页上获取的数据,虽然不真实,但更适合于演示。于Northwind不同的是,为了示例, 所有的数据库操作全使用存储过程来完成。

点击此处下载示例及文档。   (2011-11-26 最后更新)

回到顶部

第一部分,界面截图

主菜单

基础数据包含三个部分,都比较类似,下图将展示“商品管理”页面

上图中,表格最右边的列全是TextBox,可以直接修改,然后会以Ajax的方式提交到服务器。

点击每条记录中的商品名称,将出现以下对话框,它用于新增或修改单个商品资料

新增订单界面如下

像很多C/S程序一样,“客户”可以从对话框中选择

像很多C/S程序一样,“商品”也可以从对话框中选择

数据全部录入后的样子如下图

点击按钮“确定保存此订单记录 并继续新增”,表单将以Ajax方式提交给服务器。

订单管理

页面打开后,只有“查询条件”显示在页面上

点击“查找订单”按钮,页面将以Ajax的方式向服务器发出请求,并将显示结果

点击每行中的“订单编号”,将会出现下图

示例程序还直接有“查看源代码”的功能哦

回到顶部

调用数据访问层的代码
 /// <summary>
///   操作“商品记录”的业务逻辑层
  ///   为了简单演示,每个方法将打开一个连接。
  /// </summary>
  public sealed class   ProductBLL 
 {
     public int  Insert( Product  product)
    {
         return   FishBLLHelper  . CallSpExecuteNonQuery( "InsertProduct" , product);
    }

     public int  Delete( int  productId)
    {
         return   FishBLLHelper  . CallSpExecuteNonQuery( "DeleteProduct" ,  null , productId);
    }


     public int  Update( Product  product)
    {
         return   FishBLLHelper  . CallSpExecuteNonQuery( "UpdateProduct" , product);
    }


     /// <summary>
    ///   获取指定的商品详细资料(加载所有字段)
      /// </summary>
    /// <param name="productId"></param>
    /// <returns></returns>
      public   Product  GetProductById( int  productId)
    {
         return   FishBLLHelper  . CallSpGetDataItem <  Product  > ( "GetProductById" ,  null , productId);
    }

     // 根据指定的分类ID,以及分页参数,获取商品记录列表
      public   List  <  Product  >  GetProductByCategoryId( int  categoryId,  PagingInfo  pagingInfo)
    {
         if ( categoryId  <=   0  ) {
            pagingInfo . RecCount  =   0 ;
             return new   List  <  Product  > ( 0 );
        }

         return   FishBLLHelper  . CallSpGetDataItemListPaged <  Product  > ( "GetProductByCategoryId" , pagingInfo,     categoryId);
    }


     // 搜索商品
      public   List  <  Product  >  SearchProduct( int  categoryId,  string  searchWord,  PagingInfo  pagingInfo)
    {
         return   FishBLLHelper  . CallSpGetDataItemListPaged <  Product  > ( "SearchProduct" , pagingInfo,    categoryId, searchWord);
    }


     /// <summary>
    ///   更新指定的商品数量
      /// </summary>
    /// <param name="productId"></param>
    /// <param name="quantity"></param>
    /// <returns></returns>
      public int  ChangeProductQuantity( int  productId,  int  quantity)
    {
         return   FishBLLHelper  . CallSpExecuteNonQuery( "ChangeProductQuantity" ,  null , productId, quantity);
    }

}
 /// <summary>
///   操作“订单记录”的业务逻辑层
  ///   为了简单演示,每个方法将打开一个连接。
  /// </summary>
  public sealed class   OrderBLL  :  FishBaseBLL
 {
     /// <summary>
    ///   新增订单记录(包含订单明细)
      /// </summary>
    /// <param name="order"></param>
    /// <returns></returns>
      public int  AddOrder( OrderItem  order)
    {
         // 以事务的方式创建一个FishDbContext对象,将使用默认的连接字符串
          using (  FishDbContext  db  =   new   FishDbContext ( true ) ) {
             // 添加记录到表Orders,同时获取新产生ID
              FishBLLHelper  . CallSpExecuteNonQuery(db,  "InsertOrder" , order);
            
             // 为订单明细设置OrderId,并添加到表[Order Details]
             order . Detail . ForEach(x  =>  {
                x . OrderID  =  order . OrderID;
                 FishBLLHelper  . CallSpExecuteNonQuery(db,  "InsertOrderDetail" , x);
            });

             // 刷新订单总金额。
              FishBLLHelper  . CallSpExecuteNonQuery(db,  "RefreshOrderSumMoney" ,  null , order . OrderID);

             // 提交事务。
             db . CommitTransaction();

             return  order . OrderID;
        }
    }


     // 根据指定的查询日期范围及分页参数,获取订单记录列表
      public   List  <  OrderItem  >  Search( object  dateRange,  PagingInfo  pagingInfo)
    {
         // 按分页的方式查询数据库。关于分页的查询方式请参见:CustomerBLL.GetList()
          return   FishBLLHelper  . CallSpGetDataItemListPaged2 <  OrderItem  > ( "SearchOrder" , pagingInfo, dateRange);
    }

     /// <summary>
    ///   根据订单ID获取订单相关的所有信息
      /// </summary>
    /// <param name="orderId"></param>
    /// <returns></returns>
      public   OrderItem  GetOrderById( int  orderId)
    {
         // 以非事务的方式创建一个FishDbContext对象,将使用默认的连接字符串
        // 如果一次只调用一个存储过程,则不需要创建FishDbContext对象,在调用FishBLLHelper的方法时,会自动创建(使用默认的连接字符串)
        // 这里“显式”的创建FishDbContext对象是为了让二个存储过程在一个连接内完成调用。
          using (  FishDbContext  db  =   new   FishDbContext ( false ) ) {
             OrderItem  order  =   FishBLLHelper  . CallSpGetDataItem <  OrderItem  > (db,  "GetOrderById" ,  null , orderId);
             if ( order  !=   null  ) 
                order . Detail  =   FishBLLHelper  . CallSpGetDataItemList <  OrderDetail  > (db,  "GetOrderDetails" ,  null , orderId);

             return  order;
        }
    }

     /// <summary>
    ///   修改指定的订单状态
      /// </summary>
    /// <param name="orderId"></param>
    /// <param name="finished"></param>
    /// <returns></returns>
      public int  SetOrderStatus( int  orderId,  bool  finished)
    {
         return   FishBLLHelper  . CallSpExecuteNonQuery( "SetOrderStatus" ,  null , orderId, finished);
    }
}

回到顶部

Ajax演示代码

新增订单,JS 代码

 function  btnSubmit_click() {
     if ( $( "#hfProductIdList" ).val().length  ==   0  ){
        $.messager.alert(g_MsgBoxTitle ,   "没有明细项目不能保存。"  ,   "warning" );  return false ;
    }
    
     // 获取订单明细项目,组合成一个字符串,格式:id=quantity;
      var  detail  =   '' ;
    $( "#tblOrderDetail input[name^=quantity_]" ).each( function (){
        detail  +=  $( this ).attr( "name" ).substring( 9 )  +   "="   +  $( this ).val()  +   ";" ;
    });
    $( "#hfOrderDetail" ).val(detail);
     
     // 向服务器提交表单。注意URL参数。
      var  j_dialog  =  ShowWaitMessageDialog();
      $(    "form"  ).ajaxSubmit({ url  :     "/AjaxOrder.AddOrder.cs"   ,
         complete :   function () { HideWaitMessageDialog(j_dialog); } ,
         success :   function (responseText ,  statusText) {
             if  (responseText  ==   "1" )
                $.messager.alert(g_MsgBoxTitle ,   "操作成功"  ,   "info"  ,   function (){ window.location  =  window.location; });
             else
                 $.messager.alert(g_MsgBoxTitle ,   "提交失败,错误消息或代码:<br />"   +  responseText  ,  'error' );
        }
    });
     return false ;
}

新增订单,C# 代码

 /// <summary>
///   Ajax服务类,提供“订单记录”相关操作
  /// </summary>
  public static class   AjaxOrder
 {
     //--------------------------------------------------------------
    // 注意: 
    //     用于Ajax的类,可以是静态的,方法也可以是静态的。
    //--------------------------------------------------------------

      /// <summary>
    ///   新增订单
      /// </summary>
    /// <param name="form"></param>
    /// <returns></returns>
      public static int  AddOrder( OrderSubmitForm  form)
    {
         OrderItem  order  =  form . ConvertToOrderItem();
         int  newOrderId  =   BllFactory  . GetOrderBLL() . AddOrder(order);
         return  (newOrderId  >   0   ?   1  :  0 );
    }
}


 public sealed class   OrderSubmitForm  :  MyDataItem
 {
     public   DateTime  OrderDate;
     public int  CustomerID;
     public string  OrderDetail;
     public string  Comment;
}

显示订单明细对话框,JS 代码

 function  ShowOrderDialog(){
     var  dom  =   this ;
     var  orderId  =  $( this ).attr( "OrderNo" );
      var     url   =   "/AjaxOrder.Show.cs?id="   +     orderId;  
    ShowViewerDialog( "divOrderInfo"  ,  url ,   function (){
        $( "#tblOrderDetail" ).SetGridStyle().find( "a.easyui-linkbutton" ).linkbutton().click(ShowProductDialog);
        $( "#btnSetOrderStatus" ).linkbutton().click( function (){    SubmitSetOrderStatus( orderId ,  dom );  return false ; });
    } ,   800  ,   530 );
     return false ;
}

显示订单明细对话框,C# 代码

 public static class   AjaxOrder
 {
     public static string  Show( int  id)
    {
         if ( id  <=   0  )
             throw new   MyMessageException ( "没有指定OrderId" );

         OrderItem  item  =   BllFactory  . GetOrderBLL() . GetOrderById(id);
         if ( item  ==   null  )
             throw new   MyMessageException ( "指定的ID值无效。不能找到对应的记录。" );

         // 执行用户控件,并返回生成的HTML代码,用户控件呈现所需要的数据通过第二个参数传递。
          return  FishWebLib . Ajax .  UcExecutor  . Execute( "~/Controls/OrderInfo.ascx" , item);
    }
}

 public sealed class   OrderItem  :  MyDataItem
 {
     public int  OrderID {  get ;  set ; }
     public int  ?  CustomerID {  get ;  set ; }
     public   DateTime  OrderDate {  get ;  set ; }
     public decimal  SumMoney {  get ;  set ; }
     public string  Comment {  get ;  set ; }
     public bool  Finished {  get ;  set ; }
     public string  CustomerName {  get ;  set ; }


     public   List  <  OrderDetail  >  Detail;
}

OrderInfo.ascx代码如下(并没有与之对应的cs代码哦,关于这个,以后再谈)

 <%  @   Control   Language  ="C#"   Inherits  ="FishWebLib.Mvc.MyUserControlView<OrderItem>"   %>

  <  table   cellpadding  ="4"   cellspacing  ="0"   style  ="  width :  99%">
<  tr  ><  td   style  ="  width :  60px"> 订单日期 </  td  ><  td  >
    <  input   type  ="text"   class  ="myTextbox"   readonly  ="readonly"   style  ="  width :  200px"  
			 value  ="  <% = Model.OrderDate.ToString("yyyy-MM-dd HH:mm:ss")  %>  " />
    </  td  ></  tr  >
<  tr  ><  td  > 客户 </  td  ><  td  >
    <  input   type  ="text"   class  ="myTextbox"   readonly  ="readonly"   style  ="  width :  400px"  
			 value  ="  <% = Model.CustomerName.HtmlEncode()  %>  " />
    </  td  ></  tr  >
<  tr  ><  td   class  ="vertical"> 订单明细 </  td  ><  td  >
    <  table   cellpadding  ="4"   cellspacing  ="0"    id  ="tblOrderDetail"   class  ="GridView">
        <  tr  >
            <  td   style  ="  width :  450px"> 商品名称 </  td  >
            <  td   style  ="  width :  60px"> 单位 </  td  >
            <  td   style  ="  width :  60px"> 数量 </  td  >
            <  td   style  ="  width :  60px"> 单价 </  td  >
        </  tr  >        
  <%   foreach (  var  item  in  Model . Detail ) {  %>
  <  tr  >
    <  td  ><  a   href  ="#"   ProductId  ="  <% = item.ProductID  %>  "   class  ="easyui-linkbutton"   plain  ="true"> 
			 <%  =  item . ProductName . HtmlEncode()  %>  </  a  ></  td  >
    <  td  >  <%  =  item . Unit . HtmlEncode() %>  </  td  >
    <  td  >  <%  =  item . Quantity  %>  </  td  >
    <  td  >  <%  =  item . UnitPrice . ToString( "F2" )  %>  </  td  >
</  tr  >
  <%  }  %>
          <  tr  ><  td   colspan  ="4"   style  ="  text-align :  right ;  padding-right :  10px ; ">
             订单总金额: <  b  >  <%  =  Model . SumMoney . ToText()  %>  </  b  >
        </  td  ></  tr  >        
    </  table  >
</  td  ></  tr  >

<  tr  ><  td   class  ="vertical"> 备注 </  td  ><  td  >
    <  textarea   class  ="myTextbox"   style  ="  width :  660px ;  height :  70px"   readonly  ="readonly" > 
			 <%  =  Model . Comment . HtmlEncode() %>  </  textarea  >
    </  td  ></  tr  >
<  tr  ><  td  ></  td  ><  td  >
    <  label  >  <%  =  Model . Finished . ToCheckBox( "chkFinished" ,  null ,  false )  %> 订单已处理 </  label  >      &nbsp;&nbsp;&nbsp;
          <  a   id  ="btnSetOrderStatus"   href  ="#"   class  ="easyui-linkbutton"   iconCls  ="icon-ok"> 修改订单状态 </  a  >        
    </  td  ></  tr  >
</  table  >
 

回到顶部

组件性能测试

我在写这二个组件时,就很关心性能问题,因此特意写了二个性能的测试项目。

本演示程序的压缩包解开后,其中有二个目录(TestAjaxPerformance 和 TestDALPerformance)分别是测试数据访问层和Ajax框架性能的。

TestDALPerformance是用于测试数据访问层的项目, 对比的对象是“手工代码方式”和Linq to SQL, EF框架

我自己在我的笔记本上测试过,比微软的同类框架要快。不信您可以自己去运行起来看一下。

回到顶部

用户手册,API文档

为了简单,贴图算了。

点击此处下载示例及文档。   (2011-11-26 最后更新)

作者: Leo_wl

    

出处: http://www.cnblogs.com/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于Ajax服务端框架的综合示例的详细内容...

  阅读:47次