我开发的内部ORM已经历时3年多。前前后后、断断续续,历经3个版本。
以下是其中的“数据库组件”的功能示例,欢迎大家给出宝贵的建议和意见:
对数据库的操作主要通过BLL<T>和BLL<T>.Query。BLL<T>.Query实现查询逻辑,负责收集查询条件参数及缓存逻辑,最终对数据库的操作还是调用BLL<T>来实现。其中部分操作只在BLL<T>中支持。以下按CURD分别讲解:
一、添加
1. object Add(string[] columns, object[] objs) 使用objs,添加columns等列
Eg: id = Transform.Int(CommentBLL.Instance.Add(new string[] { "title", "content" }, new object[] { title, content }));
Sql: INSERT [Comment](title,content) VALUES(@title,@content);SELECT SCOPE_IDENTITY();
2. object Add(T obj, string[] columns) 添加obj的columns等列
Eg: id = Transform.Int(CommentBLL.Instance.Add(obj, new string[] { "title", "content" }));
Sql: INSERT [Comment](title,content) VALUES(@title,@content);SELECT SCOPE_IDENTITY();
3.object Add(T obj) 添加obj(除自增列外所有列)
Eg: id = Transform.Int(CommentBLL.Instance.Add(obj));
Sql: INSERT [Comment](title,content,userId,userName) VALUES(@title,@content,@userId,@userName);SELECT SCOPE_IDENTITY();
注:A.所有添加方法返回值规则都一样,有自增列,返回自增值(SCOPE_IDENTITY()),没自增列返回1.
B.添加各种方法只在BLL<T>类中,另外还有些涉及缓存的重载需要在BLL<T>继承类中才可以调用
二、修改
1.bool Update(T obj, string[] columns) 修改obj的columns等列
该方法是BLL<T>的实例方法
Eg: bool state = CommentBLL.Instance.Update(obj, new string[] { "title", "content" });
Sql: UPDATE [Comment] SET [title]=@title1,[content]=@content1 WHERE [id]=@id
2.bool Update(T obj) 按主键修改obj
该方法是BLL<T>的实例方法
Eg: bool state = CommentBLL.Instance.Update(obj);
Sql: UPDATE [Comment] SET [title]=@title1,[content]=@content1,[userId]=@userId1,[userName]=@userName1 WHERE [id]=@id
- bool Update(string statement, params object[] data) 按statement及其参数(data)字句修改
Eg: CommentBLL.Query q = CommentBLL.Instance.Where("id=@id").Parms(id);
q.Update("title=@title,content=@content", title, content);
Sql: UPDATE [Comment] SET title=@title,content=@content WHERE id=@id
注:该方法是BLL<T>.Query的实例方法(BLL<T>不提供该方法,在没有条件限制下容易导致误操作,修改当前表中的所有数据)
三、读取
读取即为查询是数据操作中最主要、最复杂的部分,分为以下几类:
一) 单个数据(单行单列)
1.object GetColumn(string columnName)
在BLL<T>和BLL<T>.Query中都有该实例方法,主要是使用BLL<T>.Query里面的那个实例方法, Query可以指定查询条件(一般情况下没有条件的获取一行数据是没有意义的)
Eg: BLL<ErrorLog>.Query q = ErrorLog.BLL.Where("LogId=@id").Parms(id);
LogContent = Transform.Str(q.GetColumn("LogContent"));
Sql: SELECT TOP 1 LogContent FROM [JiaTxErrorLog] WHERE LogId=@id
二) 单条数据
1.T ViewByKeys(params object[] keys) 按主键获取一条数据
BLL<T>的实例方法
Eg: ErrorLog log = ErrorLog.BLL.ViewByKeys(id);
Sql: SELECT TOP 1 logId,logUrl,logDate,LogContent,logCategory,logUserIp,logCity,logErrorDescription FROM [JiaTxErrorLog] WHERE [LogId]=@id
2.T ShowByKeys(params object[] keys) 按主键获取一条数据(如果没有返回New T())
BLL<T>的实例方法
Eg: ErrorLog log = ErrorLog.BLL.ShowByKeys(id);
Sql: SELECT TOP 1 logId,logUrl,logDate,LogContent,logCategory,logUserIp,logCity,logErrorDescription FROM [JiaTxErrorLog] WHERE [LogId]=@id
3.T Get() 获取一行数据
在BLL<T>和BLL<T>.Query中都有该实例方法,主要是使用BLL<T>.Query里面的那个实例方法, Query可以指定查询条件(一般情况下没有条件的获取一行数据是没有意义的)
BLL<ErrorLog>.Query q = ErrorLog.BLL.Where("LogId=@id").Parms(id);
ErrorLog log = q.Get();
Sql: SELECT TOP 1 logId,logUrl,logDate,LogContent,logCategory,logUserIp,logCity,logErrorDescription FROM [JiaTxErrorLog] WHERE LogId=@id
4.object[] GetColumns(params string[] columns) 获取columns等列单行数据
在BLL<T>和BLL<T>.Query中都有该实例方法,主要是使用BLL<T>.Query里面的那个实例方法, Query可以指定查询条件(一般情况下没有条件的获取一行数据是没有意义的)
Eg: BLL<ErrorLog>.Query q = ErrorLog.BLL.Where("LogId=@id").Parms(id);
object[] cols = q.GetColumns("logUrl", "LogContent");
Sql: SELECT TOP 1 logUrl,LogContent FROM [JiaTxErrorLog] WHERE LogId=@id
三) 取数据列表
1.List<T> List(int num, int start) 从start条开始获取num条数据
在BLL<T>和BLL<T>.Query中都有该实例方法
Eg: BLL<ErrorLog>.Query q = ErrorLog.BLL.Where("LogUrl like @LogUrl").Parms("/jiancai/%");
list = q.List(10, 10);
Sql: WITH _T AS(SELECT TOP 20 ROW_NUMBER() OVER(ORDER BY logId) AS _I,logId AS _logId FROM [JiaTxErrorLog] WITH(NOLOCK) WHERE LogUrl like @LogUrl)SELECT TOP 10 [logId],[logUrl],[logDate],[logContent],[logCategory],[logUserIp],
[logCity],[logErrorDescription] FROM [JiaTxErrorLog] _A WITH(NOLOCK),_T WHERE _A.logId=_T._logId AND _I>10 ORDER BY _I;
2.List<T> List0(int page, int size) 以size条数据为一页,获取page页数据
在BLL<T>和BLL<T>.Query中都有该实例方法
Eg: BLL<ErrorLog>.Query q = ErrorLog.BLL.Where("LogUrl like @LogUrl").Parms("/jiancai/%");
list = q.List0(1, 10);
Sql: SELECT TOP 10 [logId],[logUrl],[logDate],[logContent],[logCategory],[logUserIp],[logCity],[logErrorDescription] FROM [JiaTxErrorLog] WITH(NOLOCK) WHERE LogUrl like @LogUrl ORDER BY logId
3.int List(List<T> list, int num, int start) 从start条开始获取num条数据及总数
Eg: BLL<ErrorLog>.Query q = ErrorLog.BLL.Where("LogUrl like @LogUrl").Parms("/jiancai/%");
int count = q.List(list, 10, 10);
Sql: SELECT count(1) FROM [Comment] WITH(NOLOCK) WHERE LogUrl like @LogUrl; WITH _T AS(SELECT TOP 20 ROW_NUMBER() OVER(ORDER BY logId) AS _I,logId AS _logId FROM [JiaTxErrorLog] WITH(NOLOCK) WHERE LogUrl like @LogUrl)SELECT TOP 10 [logId],[logUrl],[logDate], [logContent],[logCategory],[logUserIp],[logCity],[logErrorDescription] FROM [JiaTxErrorLog] _A WITH(NOLOCK),_T WHERE _A.logId=_T._logId AND _I>10 ORDER BY _I;
4. int List0(List<T> list, int page, int size) 以size条数据为一页,获取page页数据及总数
Eg: BLL<ErrorLog>.Query q = ErrorLog.BLL.Where("LogUrl like @LogUrl").Parms("/jiancai/%");
int count = q.List(list, 2, 10);
Sql同int List(List<T> list, int num, int start)
5. List<T> ListAll() 获取所有(符合条件)数据
在BLL<T>和BLL<T>.Query中都有该实例方法(大数据量的表慎用)
Eg: BLL<Comment>.Query q = CommentBLL.Instance.Where("userName=@userName").Parms("张三");
List<Comment> list = q.ListAll();
Sql: SELECT [id],[title],[content],[userId],[userName],[state] FROM [Comment] WITH(NOLOCK) WHERE userName=@userName ORDER BY id desc
6. List<object[]> ListColumns(int num, int start, params string[] columns) 从start条开始获取num条columns等列数据
在BLL<T>和BLL<T>.Query中都有该实例方法
Eg: BLL<ErrorLog>.Query q = ErrorLog.BLL.Where("LogUrl like @LogUrl").Parms("/jiancai/%");
List<object[]> datas = q.ListColumns(10, 0, "logUrl", "LogContent");
Sql: SELECT TOP 10 [logUrl] [logContent] FROM [JiaTxErrorLog] WITH(NOLOCK) WHERE LogUrl like @LogUrl ORDER BY logId
7. List<object[]> ListColumnsAll(params string[] columns) 获取所有(符合条件) columns等列数据
在BLL<T>和BLL<T>.Query中都有该实例方法
Eg: BLL<Comment>.Query q = CommentBLL.Instance.Where("userName=@userName").Parms("张三");
List<object[]> list = q.ListColumnsAll("Title", "Content");
Sql: SELECT [title],[content] FROM [Comment] WITH(NOLOCK)
WHERE userName=@userName ORDER BY id desc
8. List<object[]> GroupList(string[] by, string[] columns, int num, int start) 从start条开始获取num条按by等列分组的columns等列数据
在BLL<T>和BLL<T>.Query中都有该实例方法
Eg: BLL<Comment>.Query q = CommentBLL.Instance.Where("title like @title").Parms("%精华%");
List<object[]> list = q.GroupList(new string[] { "userName" }, new string[] { "userName", "count(1)" } , 10, 0);
Sql: SELECT TOP 10 userName,count(1) FROM [Comment] WITH(NOLOCK) WHERE title like @title AND [state]=1 GROUP BY userName
9. List<object[]> GroupAll(string[] by, string[] columns) 获取所有按by等列分组的columns等列数据
在BLL<T>和BLL<T>.Query中都有该实例方法
Eg: BLL<Comment>.Query q = CommentBLL.Instance.Where("title like @title").Parms("%精华%");
List<object[]> list = q.GroupAll(new string[] { "userName" }, new string[] { "userName", "count(1)" });
Sql: SELECT userName,count(1) FROM [Comment] WITH(NOLOCK) WHERE title like @title AND [state]=1 GROUP BY userName
四) 统计数据量
- int Count() 获取所有(符合条件)数据条数
在BLL<T>和BLL<T>.Query中都有该实例方法
Eg: BLL<Comment>.Query q = CommentBLL.Instance.Where("userName=@userName").Parms("张三");
int count = q.Count();
Sql: SELECT count(1) FROM [Comment] WITH(NOLOCK) WHERE userName=@userName
2. int GroupCout(string[] by) 获取所有按by等列分组数
在BLL<T>和BLL<T>.Query中都有该实例方法
Eg: BLL<Comment>.Query q = CommentBLL.Instance.Where("title like @title").Parms("%精华%");
int count = q.GroupCout(new string[] { "userName" });
Sql: DECLARE @I INT;SET @I=0;SELECT @I=@I+1 FROM [Comment] WITH(NOLOCK) WHERE title like @title AND [state]=1 GROUP BY userName;SELECT @I;
四、删除
删除分为逻辑状态删除和物理删除,逻辑状态删除为UPDATE状态字段为0, 物理删除为DELETE,通过在当前Mode类的DbTableAttribute的属性DelField来申明
1.用DelField申明逻辑状态删除
Eg: [DbTable("Comment", DelField = "state")]
public class Comment
示例说明:A:以上说明"state"是逻辑删除的状态字段,对于表"Comment"的所有查询都会追加条件"[state]=1",所有删除都切换为"UPDATE Comment SET [state]=0"。
B: DelField字段可以不定义在Mode类中(数据库中要设置默认值为1)
2.bool DelByKeys(params object[] keys) 按主键修改obj
该方法是BLL<T>的实例方法
Eg: bool state = CommentBLL.Instance.DelByKeys(id);
逻辑删除Sql: UPDATE [Comment] SET [state]=0 WHERE [id]=@id AND [state]=1
物理删除Sql: DELETE [Comment] WHERE [id]=@id
3.bool Del() 按Query提供条件和参数删除
该方法是BLL<T>.Query的实例方法(BLL<T>不提供该方法,在没有条件限制下容易导致误操作,删除当前表中的所有数据)
Eg: CommentBLL.Query q = CommentBLL.Instance.Where("id=@id").Parms(id);
bool state = q.Del();
逻辑删除Sql: UPDATE [Comment] SET [state]=0 WHERE [id]=@id AND [state]=1
物理删除Sql: DELETE [Comment] WHERE [id]=@id
五、 Query查询及缓存
1. Query CopyQuery() 创建一个新Query对象
在BLL<T>和BLL<T>.Query中都有该实例方法(在Query中复制当前对象)
Eg: CommentBLL.Query q = CommentBLL.Instance.CopyQuery();
2. Query Where(params string[] conditions) 按conditions等条件查询
在BLL<T>是使用conditions等条件创建一个Query对象
在BLL<T>是使用conditions等条件设置(覆盖,并覆盖原参数列表Parms)Query对象中的条件
Eg: BLL<Comment>.Query q = CommentBLL.Instance.Where("userName=@userName").Parms("张三");
int count = q.Count();
Sql: SELECT count(1) FROM [Comment] WITH(NOLOCK) WHERE userName=@userName
3. Query In(string field, params object[] data) 按field的多个值获取
在BLL<T>和BLL<T>.Query中都有该实例方法
Eg: BLL<Comment>.Query q = CommentBLL.Instance.In("userName", "张三", "李四");
int count = q.Count();
Sql: SELECT COUNT(1) FROM [Comment] WITH(NOLOCK)
WHERE userName IN(@userName,@userName1)
注:参数data是object[]类型,在.net2.0中int[]、long[]等数组不能直接使用(其他类型数组会作为data的第一个元素导致出错),需要转化为object[]类型才可以使用
Eg:object[] data = new object[catalogChildIdCount + 1];
catalogChildIds.CopyTo(data, 0);
catalogIds[catalogChildIdCount] = catalogId;
query.In("catalogId", data);
4. Query OrderBy(string orderby) 按orderby排序查询
在BLL<T>是使用orderby排序创建一个Query对象
在BLL<T>是使用orderby排序设置(覆盖)Query对象中的排序
Eg: BLL<Comment>.Query q = CommentBLL.Instance.OrderBy("userId desc");
List<Comment> list = q.ListAll();
Sql: SELECT [id],[title],[content],[userId],[userName],[state] FROM [Comment] WITH(NOLOCK) ORDER BY userId desc
注:多个排序以","分隔,但是不能以"order by"开始
5.Query ExistJoin(IQuery query, string on) 创建联表查询对象
在BLL<T>和BLL<T>.Query中都有该实例方法
Eg: int count = UserBLL.Instance.ExistJoin(CommentBLL.Instance, "id=userId").Count();
Sql: SELECT COUNT(1) FROM [User] WITH(NOLOCK) WHERE EXISTS(SELECT 1 FROM [Comment] WITH(NOLOCK) WHERE [User].ID=USERID)
6. Query Cache(string cacheName)
是BLL<T>的protected实例方法,只有在BLL<T>的继承类中调用。(本框架限制任意使用缓存,对该类的缓存只能统一在该BLL(业务逻辑)类中制定,避免缓存冲突和滥用)
Eg://CommentBLL : BLL<Comment>
public int CountWithCache()
{
return Cache("Count").Count();
}
7. Query Parms(params object[] prams) 增加查询参数
是BLL<T>.Query的实例方法
Eg: BLL<Comment>.Query q = CommentBLL.Instance.Where("userName=@userName").Parms("张三");
int count = q.Count();
Sql: SELECT count(1) FROM [Comment] WITH(NOLOCK) WHERE userName=@userName
8. Query And(params string[] conditions) 增加查询条件
是BLL<T>.Query的实例方法
Eg: BLL<Comment>.Query q = CommentBLL.Instance.Where("title like @title").Parms("%精华%");
if (cityid > 0)
q.And("cityId=@cityId").Parms(cityid);
int count = q.Count();