近来在做一个项目,
有很多基本的信息表.
但这些信息都只有一些增删改查的相关操作
大多数表没有业务流的相关操作.
要是每个表的增删改查相关功能都一个个去做一个管理页
不单麻烦,也不算是一个程序员有的思想(不知道偷懒人程序员不算一个好的程序员)
三四十来张表.每张表做两个管理页.就是七八十人页面.
那我不想死.
所以.就打算做一个通用的增删改查控件
标题只是说一个分页显示控件,那还只是一个小点.
主要是看到现在园子里对这个做的人比效多.可能会有些点击吧.呵.
主要是以前我也做过一个那个无刷新分页的.
一下园子里就有好多人加我QQ,
有的是要源代码(那个版本JS压缩了一下),
有的是要我教jQuery,
有是就是问我那个控件怎么用.
只不过那个是用ACCESS+VS2008(jQuery+ashx+json)做的
只不过看看现在的开发.用ACC来做数据库的(大项目).那是不可能的吧
我们这个项目是用的SQL2005+VS2008
所以就在原来的基础上.更加一层的开发
(jQuery+ashx+json)
中间用到了josn的序列化与反序列化
反射,做了跨数据库接口等
当然,开始做的时候.
有一个好的设计方案是不可少的.
做的项目越多.就知道前期工作的重要性的.以前不怎么重视
在那个上面吃了大亏,就有了这个教训了
第一部分
下面是我的数据库设计,还有测试数据表结构设计
上面的五张表是控件要用的.
下面五张表是测试数据设计
第二部分
目录结构
Library里面,大家都是开发人员.这个结构看得懂吧(不知道这现设计好不好)
AjaxPages里面就是放ashx请求处理的页面的
主要是做了两个用户控件
EditGradView.ascx和ShowGradView.ascx
在ShowPage.aspx,EditPage.aspx分别引用这两个用户控件
先来看看效果吧
1.上面的按钮是功能操作的,选择结果是一个接口
就是第一列,有选择框,当你选择了哪里行的时候.点那个选择结果就会把相应的主键值传给用户,
让用户自行处理怎么操作,
当然,在我这个项目里就做了个批量删除功能了
2.增加记录
就会根据你在配置表里配置的数据,
自动生成一个表单,这个表单就是这样的
这里实现了几种控件,
文本框,密码框,日期选择框,文件上传框,下拉框,多行文本框
文本框里又有正则表达式验证(在配置表里配置你要验证的类型),
日期就会自动出来一个日历控件
文件上传.就会通过一个假的(ajax:实际是创建一个iframe)新上传.把你文件上传上去.返回一个文件名到那个框里
下拉框:当然只有外键和字典的时候.就会出来下拉了
3查询
点击查询的时候.也会自动根据你在配置表里配置的数据
自动在页页生成一个查询表单
同样也把你查询到的结果分页
3.编辑,删除,自定义
会在每行的后面出现功能操作,当然你可以配置可以不可以有这些操作
在这里.编辑就会跳到一个编辑表单让你修改
也是和增加记录的表单一样.只不过这里还要把编辑的数据绑定上去
当然,在这里功能操作里,都有相应的接口
比如我点删除的时候,要自己写一个方法,
所以我就在每个功能操作里写了一个用户接口
只要你引用了的页面里写了一个这样的接口,
就会去调用你自己写的方法,没有的话.就执行自己写的方法
这样的话.我那个项目,三四十张表.
就可以只要配置一个配置表里面的信息
就全都可以自动的实现增删改查了
http://liuju150.cacacoo.com/
在这里可以看到效果.只不过这不是我的空间,放到别人空间上去的
那里的SQL数据库的排序规则不和我的相同.
所以中文有些乱码了.
只不过还是可以看到效果的喽.
json实体帮助类
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
Code
namespace GradView.WebApp.App_Code
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
{
public class JsonHelper
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
/// 生成Json格式
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="obj"></param>
/// <returns></returns>
public static string GetJson<T>(T obj)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
DataContractJsonSerializer json = new DataContractJsonSerializer(obj.GetType());
using (MemoryStream stream = new MemoryStream())
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
json.WriteObject(stream, obj);
string szJson = Encoding.UTF8.GetString(stream.ToArray());
return szJson;
}
}
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
/// 获取Json的Model
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="szJson"></param>
/// <returns></returns>
public static T ParseFromJson<T>(string szJson)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
T obj = Activator.CreateInstance<T>();
using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(szJson)))
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
DataContractJsonSerializer serializer = new DataContractJsonSerializer(obj.GetType());
return (T)serializer.ReadObject(ms);
}
}
}
}
json数据表帮助类
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
Code
namespace GradView.WebApp.App_Code
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
{
public static class JsonTableHelper
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
/// 返回对象序列化
/// </summary>
/// <param name="obj">源对象</param>
/// <returns>json数据</returns>
public static string ToJson(this object obj)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
JavaScriptSerializer serialize = new JavaScriptSerializer();
return serialize.Serialize(obj);
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
/// 控制深度
/// </summary>
/// <param name="obj">源对象</param>
/// <param name="recursionDepth">深度</param>
/// <returns>json数据</returns>
public static string ToJson(this object obj, int recursionDepth)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
JavaScriptSerializer serialize = new JavaScriptSerializer();
serialize.RecursionLimit = recursionDepth;
return serialize.Serialize(obj);
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
/// DataTable转为json
/// </summary>
/// <param name="dt">DataTable</param>
/// <returns>json数据</returns>
public static string ToJson(DataTable dt)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
Dictionary<string, object> dic = new Dictionary<string, object>();
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
int index = 0;
foreach (DataRow dr in dt.Rows)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
Dictionary<string, object> result = new Dictionary<string, object>();
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
foreach (DataColumn dc in dt.Columns)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
result.Add(dc.ColumnName, dr[dc].ToString());
}
dic.Add(index.ToString(), result);
index++;
}
return ToJson(dic);
}
}
}
http://www.cnblogs.com/liuju150/archive/2009/09/11/1565009.html
这里是表单的反射操作
数据操作方法
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
Code
namespace GradView.Library.Data
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
///Title: Classinfo类
///Description: Classinfo业务逻辑操作类
///@author LiuJu
///@version 1.0.0.0
///@date 2009-8-29
///@modify
///@date
/// </summary>
[DataObject(true)]
public partial class BizClassinfo
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
private static IDataBaseOperate< Classinfo> baseOperate =(IDataBaseOperate< Classinfo>) DaoFactory.CreateInstance("DaoClassinfo");
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
BaseOperation#region BaseOperation
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
/// 在dbo.ClassInfo中增加一条记录
/// </summary>
/// <param name="model">包含被插入数据的实体对象</param>
/// <returns>影响行数</returns>
[DataObjectMethod(DataObjectMethodType.Insert)]
public static int Insert(Classinfo model)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if(model != null)
return baseOperate.Insert(model);
else
throw new ApplicationException("在dbo.ClassInfo中增加一条记录时,传递的参数model为Null!");
}
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
/// 在dbo.ClassInfo中新增一条记录,支持数据库事务
/// </summary>
/// <param name="model">包含被插入数据的实体对象</param>
/// <param name="trans">事务参数</param>
/// <returns>影响行数</returns>
[DataObjectMethod(DataObjectMethodType.Insert)]
public static int Insert(Classinfo model,object trans)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if(model != null && trans !=null)
return baseOperate.Insert(model,trans);
else
throw new ApplicationException("在dbo.ClassInfo中增加一条记录时,传递的参数model,trans有错误!");;
}
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
/// 在dbo.ClassInfo中删除一条记录
/// </summary>
/// <param name="model">包含主键值的实体对象</param>
/// <returns>所影响的行数</returns>
[DataObjectMethod(DataObjectMethodType.Delete)]
public static int Delete(Classinfo model)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if(model != null)
return baseOperate.Delete(model);
else
throw new ApplicationException("在dbo.ClassInfo中删除一条记录时,传递的参数model为Null!");;
}
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
/// 在dbo.ClassInfo中删除一条记录,支持数据库事务
/// </summary>
/// <param name="model">包含主键值的实体对象</param>
/// <param name="trans">事务参数</param>
/// <returns>所影响的行数</returns>
[DataObjectMethod(DataObjectMethodType.Delete)]
public static int Delete(Classinfo model,object trans)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if(model != null && trans !=null )
return baseOperate.Delete(model,trans);
else
throw new ApplicationException("在dbo.ClassInfo中删除一条记录时,传递的参数model,trans有错误!");
}
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
/// 在dbo.ClassInfo中完整更新一条记录
/// </summary>
/// <param name="model">包含被更新数据的实体对象</param>
/// <returns>影响行数</returns>
[DataObjectMethod(DataObjectMethodType.Update)]
public static int Update(Classinfo model)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if(model != null)
return baseOperate.Update(model);
else
throw new ApplicationException("在dbo.ClassInfo中更新一条记录时,传递的参数model为Null!");
}
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
/// 在dbo.ClassInfo中完整更新一条记录,支持数据库事务
/// </summary>
/// <param name="model">包含被更新数据的实体对象</param>
/// <param name="trans">事务参数</param>
/// <returns>影响行数</returns>
[DataObjectMethod(DataObjectMethodType.Update)]
public static int Update(Classinfo model,object trans)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if(model != null && trans !=null)
return baseOperate.Update(model,trans);
else
throw new ApplicationException("在dbo.ClassInfo中更新一条记录时,传递的参数model,trans有错误!");
}
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
/// 根据指定的Sql更新dbo.ClassInfo表中的一条记录
/// </summary>
/// <param name="sql">Update的Sql语句</param>
/// <param name="parms">sql参数</param>
/// <returns>返回数据库受影响的记录数</returns>
[DataObjectMethod(DataObjectMethodType.Update)]
public static int Update(string sql, object[] parms)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if(sql != null && parms !=null)
return baseOperate.Update(sql,parms);
else
throw new ApplicationException("根据指定的Sql在dbo.ClassInfo中更新一条记录时,传递的参数sql,parms有错误!");
}
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
/// 根据指定的Sql更新dbo.ClassInfo表中的一条记录,支持数据库事务.
/// </summary>
/// <param name="sql">Update的Sql语句</param>
/// <param name="parms">sql参数</param>
/// <param name="trans">事务参数</param>
/// <returns>返回数据库受影响的记录数</returns>
[DataObjectMethod(DataObjectMethodType.Update)]
public static int Update(string sql, object[] parms, object trans)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if(sql != null && parms !=null && trans !=null)
return baseOperate.Update(sql,parms,trans);
else
throw new ApplicationException("根据指定的Sql在dbo.ClassInfo中更新一条记录时,传递的参数sql,parms,trans有错误!");
}
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
/// 根据主键获取dbo.ClassInfo中的一条记录
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
[DataObjectMethod(DataObjectMethodType.Select)]
public static Classinfo GetModel(Classinfo model)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if(model != null )
return baseOperate.GetModel(model);
else
throw new ApplicationException("根据主键获取dbo.ClassInfo中的一条记录时,传递的参数model为Null!");
}
// <summary>
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// 根据指定的SQL获取dbo.ClassInfo中的一条记录
/// </summary>
/// <param name="sql">SQL语句</param>
/// <returns>实体对象</returns>
[DataObjectMethod(DataObjectMethodType.Select)]
public static Classinfo GetModel(string sql,object[] parms)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if(!string.IsNullOrEmpty(sql))
return baseOperate.GetModel(sql,parms);
else
throw new ApplicationException("根据指定的SQL获取dbo.ClassInfo中的一条记录时,传递的参数sql为Null!");
}
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
/// 在dbo.ClassInfo中获取所有记录
/// </summary>
/// <returns></returns>
[DataObjectMethod(DataObjectMethodType.Select)]
public static IList<Classinfo> GetList()
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
return baseOperate.GetList();
}
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
/// 根据指定的SQL在dbo.ClassInfo中获取所有记录
/// </summary>
/// <param name="sql">SQL语句</param>
/// <returns>记录集</returns>
[DataObjectMethod(DataObjectMethodType.Select)]
public static IList<Classinfo> GetList(string sql,object[] parms)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if(!string.IsNullOrEmpty(sql))
return baseOperate.GetList(sql,parms);
else
throw new ApplicationException("根据指定的SQL在dbo.ClassInfo中获取所有记录时,传递的参数sql为Null!");
}
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
/// 在dbo.ClassInfo中查询某条记录是否存在
/// </summary>
/// <param name="model">包含主键值的实体对象</param>
/// <returns>存在返加true,不存在返回false</returns>
[DataObjectMethod(DataObjectMethodType.Select)]
public static bool Exists(Classinfo model)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if(model != null )
return baseOperate.Exists(model);
else
throw new ApplicationException("在dbo.ClassInfo中查询某条记录是否存在时,传递的参数model为Null!");
}
#endregion
}
}
续前面的无刷新分页控件,编辑,修改控件的实现,
(这里是地址:http://www.cnblogs.com/liuju150/archive/2009/09/11/1564994.html)
那么,有三四十张表的话,
前台表单是自动生成的.
只不过生成的实体和数据库里的表名都是有规律可以找的.
还有操作实体的类,
所以我只要通过前台把表单传过来.
我就可以知道要反射到哪个实体,
然后对实体进行相应的赋值.
再反射一个实体操作的类.
就可以实现对实体的增删改操作了
上面是我的数据库表名
下面是我的实体,和实体操作的类名
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
Code
private void InsertAndUpdateObj(HttpContext context)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
string ClassName = context.Request.Form["ClassName"].ToString();
string ClassData = context.Request.Form["ClassData"].ToString();
string IntOrUpd = context.Request.Form["isIns"].ToString();
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
string[] ClassNameArray = ClassName.Split('_');
string CNStr = "";
for (int i = 0; i < ClassNameArray.Length; i++)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
CNStr += ClassNameArray[i].Substring(0, 1).ToUpper() + ClassNameArray[i].Substring(1).ToLower();
}
ClassName = CNStr;
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
//反射实体
Assembly Ab = Assembly.Load("GradView.Library");
Type type = Ab.GetType("GradView.Library.Data." + ClassName, true, false);
object obj = Activator.CreateInstance(type);
DataContractJsonSerializer dcjs = new DataContractJsonSerializer(type);
MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(ClassData));
obj = dcjs.ReadObject(ms);
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
//反射业务操作
string opName = "Biz" + ClassName;
string opMethod = "Insert";
switch (IntOrUpd)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
case "0": opMethod = "Update"; break;
case "1": opMethod = "Insert"; break;
case "2": opMethod = "Delete"; break;
default: opMethod = "Insert"; break;
}
Type opType = Ab.GetType("GradView.Library.Data." + opName, true, false);
object opObj = Activator.CreateInstance(opType);
MethodInfo[] mi = opType.GetMethods();
for (int i = 0; i < mi.Length; i++)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
if (mi[i].Name == opMethod)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
object[] par =
{
obj
};
try
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
mi[i].Invoke(opObj, par);
break;
}
catch
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
}
}
}
}
所以我只要写这样的方法来实现,
前台就可以通过jQuery把表单里的值组成json
后台接收这个json
就可以对实体进行相应的操作了