CRL是一款面向对象的轻量级ORM框架,本着快速开发,使用简便的原则,设计为
将此定义为快速开发框架,快速体现在:
还有哪些区别?
var query = Code.ProductDataManage.Instance.GetLambdaQuery(); query.Where(b => b.Id > 0); query.Join<Code.Member>((a, b) => a.UserId == b.Id).Select((a, b) => new { a.ProductName, b.Name });//筛选返回的字段 query.Join<Code.Order>((a, b) => a.UserId == b.UserId).Select((a, b) => new { orderid = b.OrderId });//筛选返回的字段 query.OrderBy(b=>b.BarCode); query.Page(15,1);
尽管条件再复杂,只要是基于LambdaQuery语法表示,都会编译成等效的存储过程
3.1后升级内容
2015-11-20 版本升级为3.1 http://www.cnblogs.com/hubro/p/4981728.html 去掉了业务类里LambdaQuery为参数的查询方法,改为直接由LambdaQuery进行查询返回 返回结果为以下类型 List<dynamic> ToDynamic() List<TResult> ToList<TResult>() List<T> ToList() Dictionary<TKey, TValue> ToDictionary<TKey, TValue>() 筛选值时,能按关联表选择了,GROUP也一样 2015-11-21 优化分页判断 修改匿名对象查询,使能正确返回值 关联查询改为查询分支了,Join方法会创建一个LambdaQueryJoin对象进行链式调用 2015-11-25 增加Nullable可空类型属性支持 public DateTime? Birthday { get; set; } 2015-11-25 优化表达式动态编译,使常量不再编译成委托 2015-12-04 优化了关联,使关联后还能关联 2015-12-07 修改字段别名判断出错 增加测试类TestAll 2015-12-11 统一函数方法查询语法,增加返回单个字段返回方法GetScalar 2015-12-15 去掉NOTIN,NOTLIKE扩展方法,扩展方法源类型改为强类型 优化缓存按主键查询方法,直接用键值查询
到目前为止,常用查询语法和函数方法已经解析完成,支持功能表现在:
语法查询优化表现在以下几个方面
查询方法修改
代码1(实现Group查询)
//Group查询
var query = Code.ProductDataManage.Instance.GetLambdaQuery();
query.Select(b => new { b.BarCode, total = b.BarCode.COUNT() }); query.Where(b => b.Id > 0); query.GroupBy(b => new { b.BarCode }); query.OrderBy(b => b.BarCode.COUNT(), true);//Group需要设置排序 query.Page(15,1);//如果要分页,设定分页参数就行了 var list = query.ToDynamic(); int total = query.RowCount;
输出
select t1.BarCode,COUNT(t1.BarCode) as total from [ProductData] t1 with(nolock) where (t1.Id>@parame0) group by t1.BarCode order by COUNT(t1.BarCode) desc
[parame0]:[0]
代码2(实现关联查询)
//关联查询
var query = Code.ProductDataManage.Instance.GetLambdaQuery();
query.Where(b => b.Id > 0); query.Join<Code.Member>((a, b) => a.UserId == b.Id).Select((a, b) => new { a.BarCode, b.Name }); query.Page(15,1);//如果要分页,设定分页参数就行了 var list = query.ToDynamic(); int total = query.RowCount;
输出
select t1.BarCode,t2.Name from [ProductData] t1 with(nolock) Inner join Member t2 with(nolock) on (t1.UserId=t2.Id) where (t1.Id>@parame0)
[parame0]:[0]
代码3(实现关联再Group)
//关联再Group查询
var query = Code.ProductDataManage.Instance.GetLambdaQuery();
query.Where(b => b.Id > 0); query.Join<Code.Member>((a, b) => a.UserId == b.Id).GroupBy((a, b) => new { a.BarCode, b.Name }).Select((a, b) => new { a.BarCode, b.Name }); query.OrderBy(b=>b.BarCode); query.Page(15,1);//如果要分页,设定分页参数就行了 var list = query.ToDynamic(); int total = query.RowCount;
输出
select t1.BarCode,t2.Name from [ProductData] t1 with(nolock) Inner join Member t2 with(nolock) on (t1.UserId=t2.Id) where (t1.Id>@parame0) group by t1.BarCode,t2.Name order by t1.BarCode desc
[parame0]:[0]
代码4(实现多次关联)
//多表关联查询
var query = Code.ProductDataManage.Instance.GetLambdaQuery();
query.Where(b => b.Id > 0); query.Join<Code.Member>((a, b) => a.UserId == b.Id).Select((a, b) => new { a.ProductName, b.Name });//筛选返回的字段 query.Join<Code.Order>((a, b) => a.UserId == b.UserId).Select((a, b) => new { orderid = b.OrderId });//筛选返回的字段 query.OrderBy(b=>b.BarCode); query.Page(15,1);//如果要分页,设定分页参数就行了 var list = query.ToDynamic(); int total = query.RowCount;
输出
select t1.ProductName,t2.Name,t3.OrderId as orderid from [ProductData] t1 with(nolock) Inner join Member t2 with(nolock) on (t1.UserId=t2.Id) Inner join OrderProduct t3 with(nolock) on (t1.UserId=t3.UserId) where (t1.Id>@parame0) order by t1.BarCode desc
[parame0]:[0]
关于分页
关于数据表创建缓存依赖
由于以上问题,可能会导至找不到字段或表的错误,当前版本作了完善,于是在后台单独开启了一个线程,用以检查表结构,在对象被首次访问后,就会添加到结构检查队列,由后台异步进行处理
在程序运行后,每个被访问过的对象会被检查一次结构,达到结构同步的目的
之前有人提到看不懂文档,希望有简单的例子,如你所愿,按基本在线销售系统写了一个Demo,以下为运行效果
此演示项目正如上面所说,采用了精简的写法实现了这些业务
继承业务封装,实现会员管理
public class MemberManage : CRL.Package.Person.PersonBusiness<MemberManage, Member>
商家和会员就都有了登录和验证方法,并实现Form认证
public ActionResult Login(Model.Member member)
{
string error; var a = MemberManage.Instance.CheckPass(member.AccountNo, member.PassWord, out error); if (!a) { ModelState.AddModelError("", error); return View(); } var u = MemberManage.Instance.QueryItem(b => b.AccountNo == member.AccountNo); if (u.Locked) { ModelState.AddModelError("", "账号已锁定"); return View(); } MemberManage.Instance.Login(u, "Member", false); string returnUrl = Request["returnUrl"]; if (string.IsNullOrEmpty(returnUrl)) { returnUrl = "/"; } return Redirect(returnUrl); }
页面上需要取当前用户,通过Form认证返回统一的Person对象
var user = MemberManage.Instance.CurrentUser;//CRL.Package.Person.Person
类似FindOne,FindList,分页方法不用去傻傻的写很多次了(一般三层结构会把这类方法写N次),已经自动转换好了
var item = ProductManage.Instance.QueryItemFromCache(b => b.Id == id);//从缓存查询 var item = ProductManage.Instance.QueryItem(b => b.Id == id);//从数据库查找
//分页
var query = ProductManage.Instance.GetLambdaQuery();
query.Where(b => b.SupplierId == CurrentUser.Id);
int count;
var result = ProductManage.Instance.Page(query, out count);
内置账户交易系统,解决多种类型支付管理问题
可以给N种角色设置N种货币类型,统一进行管理
比如以下是充值现金到会员
public bool Charge(Member member, decimal amount, string remark, TransactionType transactionType, out string error)
{
var account = Transaction.AccountManage.Instance.GetAccountId(member.Id, Model.AccountType.会员, transactionType); string orderId = DateTime.Now.ToString("yyMMddhhmmssff"); int tradeType = 10001; var trans = new List<CRL.Package.Account.Transaction>(); var ts = new CRL.Package.Account.Transaction() { AccountId = account, Amount = amount, OperateType = CRL.Package.Account.OperateType.收入, TradeType = tradeType, OutOrderId = orderId, Remark = remark }; trans.Add(ts); bool b = Transaction.TransactionManage.Instance.SubmitTransaction(out error,true, trans.ToArray());//提交流水 return b; }
确认订单时扣款,同时赠送积分
var accountUser = Transaction.AccountManage.Instance.GetAccount(order.UserId, Model.AccountType.会员, Model.TransactionType.现金);
var accountUser2 = Transaction.AccountManage.Instance.GetAccount(order.UserId, Model.AccountType.会员, Model.TransactionType.积分); if (accountUser.AvailableBalance < order.TotalAmount) { error = "账户余额不足"; return false; } int tradeType = 1001; var amount = order.TotalAmount; var orderId = order.OrderId; var remark = "订单支付"; var trans = new List<CRL.Package.Account.Transaction>(); //生成会员交易流水 var ts = new CRL.Package.Account.Transaction() { AccountId = accountUser.Id, Amount = amount, OperateType = CRL.Package.Account.OperateType.支出, TradeType = tradeType, OutOrderId = orderId, Remark = remark }; trans.Add(ts); //赠送积分 var ts3 = new CRL.Package.Account.Transaction() { AccountId = accountUser2.Id, Amount = amount, OperateType = CRL.Package.Account.OperateType.收入, TradeType = tradeType, OutOrderId = orderId, Remark = "赠送积分" }; trans.Add(ts3); bool b = Transaction.TransactionManage.Instance.SubmitTransaction(out error, trans.ToArray());//提交流水 if(!b) { return false; }
更多详细写法请对照示例和开发文档
此类演示了所有查询方式,在调用通过的情况下,达到集成测试的结果
public class TestAll { public static void TestQuery() { var instance = Code.ProductDataManage.Instance; var query = ProductDataManage.Instance.GetLambdaQuery(); query.Select(b => new { b.InterFaceUser, bb = b.Id * b.Number }); var year = DateTime.Now.Year; query.Where(b => b.Year == year);//虚拟字段 #region 扩展方法 query.Where(b => 0 < b.Id);//不再区分左边右边了 query.Where(b => b.Id < b.Number);//直接比较可以解析通过 query.Where(b => b.ProductName.Contains("122"));//包含字符串 query.Where(b => !b.ProductName.Contains("122"));//不包含字符串 query.Where(b => b.ProductName.In("111", "222"));//string in query.Where(b => b.AddTime.Between(DateTime.Now, DateTime.Now));//在时间段内 query.Where(b => b.AddTime.DateDiff(DatePart.dd, DateTime.Now) > 1);//时间比较 query.Where(b => b.ProductName.Substring(0, 3) == "222");//截取字符串 query.Where(b => b.Id.In(1, 2, 3));//in query.Where(b => !b.Id.In(1, 2, 3));//not in query.Where(b => b.UserId.Equals(Code.ProductChannel.其它));//按值等于,enum等于int query.Where(b => b.ProductName.StartsWith("abc"));//开头值判断 query.Where(b => b.Id.Between(1, 10));//数字区间 query.Where(b => b.ProductName.Like("123"));// %like% query.Where(b => b.ProductName.LikeLeft("123"));// %like query.Where(b => b.ProductName.LikeRight("123"));// like% query.Page(2, 1); var sql1 = query.PrintQuery(); var list = query.ToDynamic(); #endregion #region 关联 //索引值 query = ProductDataManage.Instance.GetLambdaQuery(); query.Join<Code.Member>((a, b) => a.UserId == b.Id && a.BarCode.Contains("1")) .SelectAppendValue(b => b.Mobile).OrderBy(b => b.Id, true); var list2 = query.ToList(); foreach (var item in list2) { var mobile = item["Mobile"]; } //按筛选值 query = ProductDataManage.Instance.GetLambdaQuery(); query.Join<Code.Member>((a, b) => a.UserId == b.Id && a.BarCode.Contains("1")) .Select((a, b) => new { a.BarCode, b.Name }).Join<Code.Order>((a, b) => a.Id == b.UserId); query.OrderBy(b => b.Id); var list3 = query.ToDynamic(); foreach (var item in list3) { var barCode = item.BarCode; } //关联再关联 query = ProductDataManage.Instance.GetLambdaQuery(); query.Join<Code.Member>((a, b) => a.UserId == b.Id && a.BarCode.Contains("1")) .SelectAppendValue(b => b.Mobile).OrderBy(b => b.Id, true).Join<Code.Order>((a, b) => a.Id == b.UserId); //按IN查询 query = ProductDataManage.Instance.GetLambdaQuery(); query.In<Code.Member>(b => b.UserId, b => b.Id, (a, b) => a.SupplierId == "10" && b.Name == "123"); var sql2 = query.PrintQuery(); #endregion #region GROUP query = Code.ProductDataManage.Instance.GetLambdaQuery(); query.Where(b => b.Id > 0); //选择GROUP字段 query.Select(b => new { sum2 = b.SUM(x => x.Number * x.Id),//等效为 sum(Number*Id) as sum2 total = b.BarCode.COUNT(),//等效为count(BarCode) as total sum11 = b.Number.SUM(),//等效为sum(Number) as sum1 b.ProductName, num1 = b.SUM(x => x.Number * x.Id), num2 = b.MAX(x => x.Number * x.Id), num3 = b.MIN(x => x.Number * x.Id), num4 = b.AVG(x => x.Number * x.Id) }); //GROUP条件 query.GroupBy(b => new { b.ProductName }); //having query.GroupHaving(b => b.Number.SUM() >= 0); //设置排序 query.OrderBy(b => b.BarCode.Count(), true);//等效为 order by count(BarCode) desc var list4 = query.ToDynamic(); foreach(var item in list4) { var total = item.total; } #endregion #region DISTINCT query = Code.ProductDataManage.Instance.GetLambdaQuery(); query.Where(b => b.Id > 0); query.DistinctBy(b => new { b.ProductName }); query.DistinctCount();//表示count Distinct 结果名为Total var list5 = query.ToDynamic(); foreach (var item in list5) { var total = item.Total; //var name = item.ProductName; } #endregion #region 函数 //按条件id>0,合计Number列 var sum = instance.Sum(b => b.Id > 0, b => b.Number * b.UserId); //按条件id>0,进行总计 var count = instance.Count(b => b.Id > 0); var max = instance.Max(b => b.Id > 0, b => b.Id); var min = instance.Min(b => b.Id > 0, b => b.Id); //使用语句进行函数查询 query = ProductDataManage.Instance.GetLambdaQuery(); query.Select(b => b.Number.SUM()); decimal sum2 = query.ToScalar(); #endregion } public static void TestUpdate() { var instance = Code.ProductDataManage.Instance; #region 更新 //要更新属性集合 CRL.ParameCollection c = new CRL.ParameCollection(); c["ProductName"] = "product1"; Code.ProductDataManage.Instance.Update(b => b.Id == 4, c); //按对象差异更新 var p = new Code.ProductData() { Id = 4 }; //手动修改值时,指定修改属性以在Update时识别,分以下几种形式 p.Change(b => b.BarCode);//表示值被更改了 p.Change(b => b.BarCode, "123");//通过参数赋值 p.Change(b => b.BarCode == "123");//通过表达式赋值 Code.ProductDataManage.Instance.Update(b => b.Id == 4, p);//指定查询更新 p = Code.ProductDataManage.Instance.QueryItem(b => b.Id > 0); p.UserId += 1; Code.ProductDataManage.Instance.Update(p);//按主键更新,主键值是必须的 #endregion #region 缓存更新 var item = Code.ProductDataManage.Instance.QueryItemFromCache(1); var guid = Guid.NewGuid().ToString().Substring(0,8); item.Change(b => b.SupplierName, guid); Code.ProductDataManage.Instance.Update(item); item = Code.ProductDataManage.Instance.QueryItemFromCache(1); var item2 = Code.ProductDataManage.Instance.QueryItem(1); var a = item.SupplierName == item2.SupplierName && item.SupplierName == guid; if (!a) { throw new Exception("更新缓存失败"); } #endregion #region 事务 string error; item = Code.ProductDataManage.Instance.QueryItem(1); var result = Code.ProductDataManage.Instance.PackageTrans((out string ex) => { ex = ""; var product = new ProductData(); product.BarCode = "sdfsdf"; product.Number = 10; ProductDataManage.Instance.Add(product); return false; }, out error); if (result) { throw new Exception("事务未回滚"); } #endregion } }
项目开源地址:https://github.com/hubro-xx/CRL3
以后所有升级更新都会基于此版本库,若重大结构变更则建新的项目
需要交流可入群,群内也不再单独上传源码包,最新源码更新此库即可
源码结构:
CRL3.1=>
CRLShoppingDemo------------->在线购物示例项目
Core.Mvc------------------------->MVC简单封装
CRL------------------------------->CRL主框架
CRL.Package--------------------->CRL业务封装
RoleControl---------------------->基于CRL实现的通用权限系统
WebTest------------------------->开发&测试文档