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 >
< 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://HdhCmsTestcnblogs测试数据/Leo_wl/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
版权信息