一个简单的ORM制作(CURD操作类)
- SQL执行类
- CURD操作类
- 其他酱油类
此篇是为上篇文章填坑的,不知道上篇砸过来的砖头够不够,不够的话请大家继续砸。
CURD操作类负责将用户提供的条件转换为SQL语句,并提供给IHelper执行,返回Model集合.

CURD类需要一个接口抽象出公共方法.便于修改和扩展,提供泛型接口。为了简单起见暂时未提供JOIN的实现,可以以数据库视图替代
public interface IDbOper<T> : IDisposable where T : new()
{
object Insert(T m);//新增MODEL,返回ID,简单起见只做了INT自增
int Update(string str);//批量更新
int Update(T m);//Model更新
int Delete();//删除
///拼接字符版,需要自己防止注入,特别是Orderby容易被忽视
IDbOper<T> Select(string sl);//选择字段
IDbOper<T> Where(string sl);
IDbOper<T> Orderby(string orby);
///Expression版重载,转化为参数方式执行,以参数方式拼接无注入风险
IDbOper<T> Select(Expression<Func<T, object>> sl);
IDbOper<T> Where(Expression<Func<T, bool>> sl);
///Dictionary版重载,需要牛顿JSON帮忙转化,以参数方式拼接无注入风险,此方式用于“等于”等查询方式,不提供大于小于查询
IDbOper<T> Orderby(Dictionary<string, string> dic);
IDbOper<T> Where(Dictionary<string, object> dic);
///
IDbOper<T> Index(int i);
IDbOper<T> Size(int i);
T First();//获取第一个model
void BegTran();
void RollBack();
void Commit();
M ToObj<M>(Func<IDataReader, M> func,string sql);
List<T> ToList();
//转化为其他类型,若开启了事务的话需要此转化
IDbOper<M> ToOper<M>() where M : new();
int Count();
//直接执行SQL语句
int DoCommand(string sql, bool issp);
}
由于比较喜欢JQ的操作方式,所以想将这种执行方式带到后台操作数据库,废话不说了先定义2个Model和实例化一个操作类
public class User
{
[Key]
public int ID{get;set;}
public string UserName{get;set;}
public string Password{get;set;}
}
public class NewUser
{
[Key]
public int ID{get;set;}
public string UserName{get;set;}
public string Password{get;set;}
}
var db=new DbOper<User>(new DbInfo(){DbType="…",DbConntion="…"});
表达式的执行
User a=db.Select(u=>new{u.ID}).Where(u=>u.ID==).First();
文本拼接的执行
User a=db.Select("*").Where("ID=54").First();
字典拼接的执行
User a=db.Select("*").Where(new Dictionary<string, object>(){Key="ID",Value=}).First();
分页代码
List<User> lt=db.Select("*").Where("ID>0").Orderby("ID Desc").Index().Size().ToList();
事务的运用
db.BegTran();
try{
int b=db.Where("ID=54").Delete();//user表删除ID=54
int c=db.ToOper<NewUser>().Insert(new NewUser(){UserName="…",Password="…"});//newuser表新增一条记录
db.Commit();
}
catch{db.RollBack();}
只有当调用Insert,Update,Delete,Count,ToList方法才会开始拼接文本再调用IHelper执行SQL语句,调用完成后会自动调用Clear()来清理保存的where,select等信息。
以下是我提供一个操作类的实现,大家也可以实现自己的操作类。
internal class DbOper<T> :IDbPhysiceOper<T>, IDisposable where T : new()
{
internal IHelper db;
internal StringBuilder where;
internal StringBuilder select;
internal StringBuilder orderby;
internal List<IDataParameter> ps;
internal StringBuilder sqlinfo;
internal int index = ;
internal int size = OrmGlobal.PageSize;//提供一个默认分页大小
private DbOper(IHelper h, StringBuilder w, StringBuilder s, StringBuilder or, List<IDataParameter> p,StringBuilder sql)
{
db = h;
where = w;
select = s;
orderby = or;
sqlinfo = sql;
ps = p;
}
internal DbOper(DbInfo info)
{ //db为上篇上定义的数据库操作类,分分种切换到其他数据库 if (info.DbType.Equals("mssql"))
{
db = new Helper.Mssql(info.DbConntion);
}
else if (info.DbType.Equals("msmars"))
{
db = new Helper.MsMars(info.DbConntion);
}
else if (info.DbType.Equals("mysql"))
{
db = new Helper.Mysql(info.DbConntion);
}
where = new StringBuilder();
select = new StringBuilder();
orderby = new StringBuilder();
sqlinfo = new StringBuilder();
ps = new List<IDataParameter>();
}
public object Insert(T m)
{
try
{
StringBuilder fields = new StringBuilder();
StringBuilder values = new StringBuilder();
List<IDataParameter> lt = new List<IDataParameter>();
string tp = string.Empty; object o = null;
foreach (var n in m.GetType().GetProperties())
{
if (n.GetCustomAttributes(typeof(ExcludeColumn), false).Length > ) { continue; }
if (n.GetCustomAttributes(typeof(Key), false).Length > ) { continue; }
o = n.GetValue(m,null);//4.5o = n.GetValue(m);
if (o == null) { continue; }
fields.Append(n.Name + ",");
tp = db.ParStr(n.Name);
values.Append(tp + ",");
lt.Add(db.Cp(tp, o));
}
if (fields.Length > ) { fields.Length--; }
if (values.Length > ) { values.Length--; }
tp = "INSERT INTO " + typeof(T).Name + "(" + fields.ToString() + ")VALUES(" + values.ToString() + ") " + db.GetIdStr;
if (OrmGlobal.isrecord) { Record(tp); }
object a = db.ExectueScalar(tp, lt, false);
Clear();
return a;
}
catch
{
OrmGlobal.DoErr(sqlinfo.ToString()); throw;
}
}
public int Update(string str)
{
try
{
string tp = "UPDATE " + typeof(T).Name + " SET " + str + (where.Length > ? " WHERE " + where : string.Empty);
if (OrmGlobal.isrecord) { Record(tp); }
int i = db.ExecuteQuery(tp, ps, false);
Clear();
return i;
}
catch
{
OrmGlobal.DoErr(sqlinfo.ToString()); throw;
}
}
public int Update(T m)
{
try
{
StringBuilder sb = new StringBuilder();
sb.Append("UPDATE " + typeof(T).Name + " SET ");
List<IDataParameter> lt = new List<IDataParameter>();
object o = null;
foreach (var n in m.GetType().GetProperties())
{//需要定义一个特性Key,以便更新Model o = n.GetValue(m,null);//4.5o = n.GetValue(m);
if (o == null) { continue; }
if (n.GetCustomAttributes(typeof(Key), false).Length > )
{
where.Append((where.Length > ? " AND " : string.Empty) + n.Name + "=" + db.ParStr(n.Name));
lt.Add(db.Cp(db.ParStr(n.Name), o));
continue;
}
sb.Append(n.Name + "=" + db.ParStr(n.Name) + ",");
lt.Add(db.Cp(db.ParStr(n.Name), o));
}
if (sb.Length > ) { sb.Length--; }
if (where.Length > ) { sb.Append(" WHERE " + where); }
var sql = sb.ToString();
if (OrmGlobal.isrecord) { Record(sql); }
int i = db.ExecuteQuery(sql, lt, false);
Clear();
return i;
}
catch
{
OrmGlobal.DoErr(sqlinfo.ToString()); throw;
}
}
public int Delete()
{
try
{
string sql = "DELETE FROM " + typeof(T).Name + (where.Length > ? " WHERE " + where : string.Empty);
if (OrmGlobal.isrecord) { Record(sql); }
int i = db.ExecuteQuery(sql, ps, false);
Clear();
return i;
}
catch
{
OrmGlobal.DoErr(sqlinfo.ToString()); throw;
}
}
public IDbOper<T> Select(string sl)
{
if (string.IsNullOrEmpty(sl)) { return this; }
select.Append((select.Length > ? "," : string.Empty) + sl); return this;
}
public IDbOper<T> Select(Expression<Func<T, object>> sl)
{
string tp=null;
using (var tp1 = new LinqVisitor())
{
tp=tp1.VisitNew(sl.Body as NewExpression);
}
return Select(tp);
}
public IDbOper<T> Where(Dictionary<string, object> dic)
{
if (dic == null || dic.Count == ) { return this; }
var sb = new StringBuilder(); string tp;
foreach (var n in dic)
{
if (sb.Length > ) { sb.Append(" AND "); }
sb.Append(n.Key);
if (n.Value is string)
{
tp = n.Value.ToString();
if (tp.Substring(tp.Length - , ) == "*")
{
sb.Append(" LIKE ");
tp = tp.Substring(, tp.Length - ) + "%";
}
else { sb.Append("="); }
ps.Add(db.Cp(db.ParStr(n.Key), tp));
}
else
{
sb.Append("=");
ps.Add(db.Cp(db.ParStr(n.Key), n.Value));
}
sb.Append(db.ParStr(n.Key));
}
Where(sb.ToString());
return this;
}
public IDbOper<T> Where(string sl)
{
if (string.IsNullOrEmpty(sl)) { return this; }
where.Append((where.Length > ? " AND " : string.Empty) + sl); return this;
}
public IDbOper<T> Where(Expression<Func<T, bool>> sl)
{
List<object> tp=null; //需要解析表达式树 using (var tp1 = new LinqVisitor())
{
tp = tp1.Visit(sl) as List<object>;
StringBuilder sb = new StringBuilder(); string s = string.Empty;
for (int i = ; i < tp.Count; i += )
{
s = db.ParStr(tp[i].ToString());
sb.Append(tp[i].ToString() + tp[i + ].ToString() + s);
if (i + < tp.Count) { sb.Append(tp[i + ]); }
ps.Add(db.Cp(s, tp[i + ]));
}
Where(sb.ToString());
}
return this;
}
public IDbOper<T> Orderby(string orby)
{
if (string.IsNullOrEmpty(orby)) { return this; }
orderby.Append((orderby.Length > ? "," : string.Empty) + orby); return this;
}
public IDbOper<T> Orderby(Dictionary<string, string> dic)
{
if (dic.Count == ) { return this; }
StringBuilder sb = new StringBuilder();
foreach (var n in dic.Keys)
{
if(string.Compare("DESC",dic[n],true)!= && string.Compare("ASC",dic[n],true)!=){continue;}
sb.Append(n + " " + dic[n] + ",");
}
if (sb.Length > ) { sb.Length--; }
Orderby(sb.ToString()); return this;
}
public IDbOper<T> Index(int i) { if (i > ) { index = i; } return this; }
public IDbOper<T> Size(int i) { if (i > ) { size = i; } return this; }
public void BegTran() { db.BegTran(); }
public void RollBack() { db.RollBack(); }
public void Commit() { db.Commit(); }
public void Clear()
{
where.Length = ; select.Length = ; orderby.Length = ; ps.Clear(); index = ; size = OrmGlobal.size;
}
public M ToObj<M>(Func<IDataReader, M> func, string sql)
{
try
{
if (OrmGlobal.isrecord) { Record(sql); }
var rd = db.ExectueReader(sql, ps, false);
M t = func(rd);
rd.Close(); Clear();
return t;
}
catch
{
OrmGlobal.DoErr(sqlinfo.ToString()); throw;
}
}
public List<T> ToList()
{
string sql = GetSql();
return ToObj<List<T>>(rd => ToList(rd),sql);
} //返回List<T>类型 public List<T> ToList(IDataReader rd)
{
var lt = new List<T>();
var set = DelegateExpr.SetMethod(typeof(T));//ExpressTree实现属性绑定,以提高Model赋值性能,可以以反射代替
while (rd.Read())
{
var m = new T();
for (var i = ; i < rd.FieldCount; i++)
{
if (rd[i] == DBNull.Value || rd[i] == null) { continue; }
set(m, rd.GetName(i).ToLower(), rd[i]);
}
lt.Add(m);
}
return lt;
}
public string GetSql()
{
return db.CreateSql(select.ToString(), typeof(T).Name, where.ToString(), orderby.ToString(), size, index);
}
public IDbOper<M> ToOper<M>() where M:new()
{
Clear();
return new DbOper<M>(db,where,select,orderby,ps,sqlinfo);
}
public int Count()
{
try
{
string sql = "SELECT COUNT(*) FROM " + typeof(T).Name + (where.Length > ? " WHERE " + where : string.Empty);
if (OrmGlobal.RecordLog) { Record(sql); }
int i= (int)db.ExectueScalar(sql, ps, false);
Clear();
return i;
}
catch
{
OrmGlobal.DoErr(sqlinfo.ToString()); throw;
}
}
public int DoCommand(string sql,bool issp)
{
int i=db.ExecuteQuery(sql,ps,issp);
Clear();
return i;
}
public void Dispose()
{
where = null; select = null; orderby = null; db.Dispose(); ps = null; sqlinfo = null;
GC.SuppressFinalize(this);
}
public T First()
{
var lt=Size().Index().ToList();
if (lt.Count > ) { return lt[]; }
return default(T);
}
~DbOper()
{
Dispose();
}
}
一个简单的ORM制作(CURD操作类)的更多相关文章
- 一个简单的ORM制作(SQL帮助类)
一个简单的ORM制作大概需要以下几个类: SQL执行类 CURD操作类 其他酱油类 先从SQL执行类说起,可能会涉及数据库的迁移等问题,所以需要定义一个接口以方便迁移到其他数据库, 事务没提供命名,若 ...
- Python 元类编程实现一个简单的 ORM
概述 什么是ORM? ORM全称"Object Relational Mapping",即对象-关系映射,就是把关系数据库的一行映射为一个对象,也就是一个类对应一个表,这样,写代码 ...
- 分享一个简单的C#的通用DbHelper类(支持数据连接池)
每次新项目的时候,都要从头去找一遍数据库工具类.这里分享一个简单实用的C#的通用DbHelper工具类,支持数据连接池. 连接池配置 <connectionStrings> <add ...
- Laravel框架简单的用户管理[CURD]操作
一个基于laravel和bootstrap的简单的用户管理,适合刚入门的我们,在做的过程中可以加深自己对laravel基础理解,里面存在一些问题,还未修改,比如css和js的引入,表单提交地址等不规范 ...
- 推荐一个很好用的HTTP操作类
/// <summary> /// 类说明:HttpHelps类,用来实现Http访问,Post或者Get方式的,直接访问,带Cookie的,带证书的等方式,可以设置代理 /// 重要提示 ...
- C#利用反射+特性实现简单的实体映射数据库操作类
附上源代码: using System; using System.Collections.Generic; using System.Data; using System.Linq; using S ...
- 用php实现一个简单的链式操作
最近在读<php核心技术与最佳实践>这本书,书中第一章提到用__call()方法可以实现一个简单的字符串链式操作,比如,下面这个过滤字符串然后再求长度的操作,一般要这么写: strlen( ...
- PHP 数据库操作类:ezSQL
EZSQL类介绍: 下载地址:http://www.jb51.net/codes/26393.htmlezsql是一个小型的快速的数据库操作类,可以让你很容易地用PHP操作各种数据库( MySQL.o ...
- Java大数操作类
Java的大数操作分为BigInteger和BigDecimal,但这两给类是分开使用的,有时候在编程的时候显得略微繁琐,现在编写了一个将二者合二为一的大数操作类. 大数操作类代码如下: packag ...
随机推荐
- 11gR2数据库日志报错:Fatal NI connect error 12170、
11gR2数据库日志报错:Fatal NI connect error 12170.TNS-12535.TNS-00505 [问题点数:100分,结帖人MarkIII] 不显示 ...
- 【面试题】Google of Greater China Test for New Grads of 2014总结
2014年Google中国校园招聘采用在线技术笔试,在Code Jam平台上,14号9点到15号9点开放测试题,帮助大家熟悉环境.这个周末也有够忙的,当时就上去看了一下,把输入文件下了一下,今天才把题 ...
- HDU 2671 Can't be easier(数学题,点关于直线对称)
题目 //数学题//直线 y = k * x + b//直线 ax+by+c=0; 点 (x0,y0); 点到直线距离 d = (ax0+by0+c)/sqrt(a^2+b^2) /********* ...
- CPLD VS FPGA
FPGA(Field-Programmable Gate Array),即现场可编程门阵列,它是在PAL.GAL.CPLD等可编程器件的基础上进一步发展的产物.它是作为专用集成电路(ASIC)领域中的 ...
- [转载] ACE 组播校验和出错问题解决
源地址:http://yuanmuqiuyu2000.blog.sohu.com/140904942.html 使用ACE框架写了个组播简单的测试工具,但是测试过程中,总是发现udp校验和出错的信息. ...
- MyEclipse 2015 CI
系统 win8.1 MyEclipse 2015 CI 激活后可用 激活工具 地址:http://download.csdn.net/detail/trep10000/8305577
- linux下文件编码的查看与修改
在Linux中查看文件编码可以通过vim编辑器来查看,在vim命令模式下输入如下命令即可: :set fileencoding //在vim中查看文件编码 如果你只是想查看其它编码格式的文件或者想解决 ...
- lintcode:背包问题
背包问题 在n个物品中挑选若干物品装入背包,最多能装多满?假设背包的大小为m,每个物品的大小为A[i] 样例 如果有4个物品[2, 3, 5, 7] 如果背包的大小为,可以选择的空间. 如果背包的大小 ...
- Shell脚本基础II
1.shell算术运算 1)加法 r=`expr 4 + 5`(注意! '4' '+' '5' 这三者之间要有空白) r=$[ 4 + 5 ] r=$(( 4 + 5 )) echo $r 2)乘法 ...
- 教你使用UIWindow实现窗口的切换
这两天写了一个手势解锁,该死的需求要求这个手势解锁页面各种出现,毕竟人家这个客户端酒20多个领导用用的,怕泄密就加了各种保密措施.先来看下需求:1.用户注册登录后跳转设置手势页面(必须设置).2.ap ...