CRL快速开发框架开源完全转到Github

时间:2021-07-26 21:04:06

CRL简介

CRL是一款面向对象的轻量级ORM框架,本着快速开发,使用简便的原则,设计为

  1. 无需关心数据库结构,CRL自动维护创建,即写即用(CRL内部有表结构检查机制,保证表结构一致性)
  2. 无需第三方工具生成代理类,标准对象结构即可
  3. 基于Linq.Expression语法解析,完全对象化操作,所有变量参数化处理,无注入安全等问题
  4. 支持join,group等常用语法和函数扩展方法
  5. 多种结果类型返回,对象,自定义对象,泛类型,字典等
  6. 多种数据库,多库支持
  7. 可封装继承的结构,充分使用面向对象的特性

使用CRL快速开发框架有哪些区别?

将此定义为快速开发框架,快速体现在:

  1. 无需关心数据表结构,框架会自动维护,只需要按面向对象的方式定义业务类
  2. 通过面向对象的特性,所有业务类和业务都可以被继承,重用
  3. 数据访问层不存在了,框架内置处理了,支持多种数据库,一些功能可能不支持,如自动编译
  4. 不像传统的三层结构,一些基本增删改查方法不需要写了,这些在业务基类中以泛类型实现过了

还有哪些区别?

  • 自动编译系统(仅MSSQL),上面讲到的的表结构自动同步也属于其中一部份,另外,对于一些复杂的查询,默认都会编译为存储过程,如分页
    对于一个分页查询,如:
    var query = Code.ProductDataManage.Instance.GetLambdaQuery();
    query.Where(b => b.Id > );
    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(,);

    尽管条件再复杂,只要是基于LambdaQuery语法表示,都会编译成等效的存储过程

  • 缓存绑定,CRL能在所有业务类创建缓存,调用非常简单,只是和数据库查询方法不同,如:
    ProductDataManage.Instance.QueryItemFromCache(1);//从缓存查询
    ProductDataManage.Instance.QueryItem(1);//从数据库查询
    并且.缓存是自动维护,过期后后台线程自动更新,在相同应用程序下,调用Update方法时,也会更新对应的缓存项
  • 内置大数据分库分表解决方案 ,通过CRL的结构,轻松实现此方案
  • 基于为oData查询形式的分布式缓存结构,实现CRL分布式对象缓存
  • CRL.Package业务封装库,对于抽象,可重复使用的业务或组件可通过CRL进行封装重用
    如会员和商家,都继承于CRL.Package.Person.Person
    共同方法,登录,密码修改,验证等方法就统一重用了

最新版由于方法和结构有所更改,升级到3.1

3.1后升级内容

--
版本升级为3.
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也一样
--
优化分页判断
修改匿名对象查询,使能正确返回值
关联查询改为查询分支了,Join方法会创建一个LambdaQueryJoin对象进行链式调用
--
增加Nullable可空类型属性支持
public DateTime? Birthday
{
get;
set;
}
--
优化表达式动态编译,使常量不再编译成委托
--
优化了关联,使关联后还能关联
--
修改字段别名判断出错
增加测试类TestAll
--
统一函数方法查询语法,增加返回单个字段返回方法GetScalar
--
去掉NOTIN,NOTLIKE扩展方法,扩展方法源类型改为强类型
优化缓存按主键查询方法,直接用键值查询

到目前为止,常用查询语法和函数方法已经解析完成,支持功能表现在:

  • Join 多表N 次关联查询
  • Sum,Count,Max,Min函数统计
  • 表Group,Distinct
  • 查询字段筛选,支持别名
  • 可为空属性类型Nullable
  • 支持虚拟字段
  • 基本逻辑判断语法和扩展函数方法
  • 多表字段排序
  • 多种结果类型返回
  • 任意查询分页

3.1主要优化内容

  1. 优化查询语法,统一了结果返回方法
  2. 增强了表结构检查,后台线程会强制检查对像与表结构一致性

更新1:语法查询优化

语法查询优化表现在以下几个方面

  • 字段间二元运算 
    query.Select(b => new {aa = b.Id * b.Number })//选择字段时二元运算 
    query.Where(b => b.Id < b.Id * b.Number)//条件选择时二元运算
  • 表达式不区分左右
    query.Where(b => 10 > b.Id);和query.Where(b => b.Id < 10 ); 等效
  • 一元运算支持 
    query.Where(b => !b.IsTop)//等效为 isTop!=1 目前只处理了BOOL类型 
    query.Where(b => !b.ProductName.Contains("122"))//BOOL类型的扩展方法同样支持
  • 关联查询支持以上所有特性
    query.Join<Code.Member>((a, b) => a.UserId == b.Id && a.Id == c).Select((a, b) => new { a.BarCode, Year2 = b.Year * b.Id }); 
    关联查询支持关联表排序 query.OrderBy<Code.Member>(b => b.Name, true)
  • 多列排序,只需调用OrderBy方法多次
    query.OrderBy(b => b.Id, true);//按ID倒序
    query.OrderBy(b => b.Name, false)//按Name正序
    结果等效为 order by Id desc,Name asc

查询方法修改

  • 使用LambdaQuery完整查询调用Page方法就可以分页了,通过ToList和ToDynamic方法返回指定类型结果
  • 当设置了关联,Group语法,也会按关联,Group语法解析
  • 当调用了Select方法筛选字段,则需要根据实际情况返回结果类型
  • 返回结果可以有以下几种类型
    • List<dynamic> ToDynamic() 按筛选值返回动态类型
    • List<TResult> ToList<TResult>() 按筛选值返回指定类型
    • List<T> ToList() 直接返回当前类型
    • Dictionary<TKey, TValue> ToDictionary<TKey, TValue>() 按筛选值返回字典(不支持分页)

示例

代码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]
  • 对于一个查询,只需调用query.Page()方法就能轻易实现分页
  • 如果需要把动态类型结果转换成定义好的对象,只需调用query.ToList<ClassName>()方法
  • 业务类中不再提供使用完整LambdaQuery作为参数的方法返回数据,而直接使用LambdaQuery的子方法返回数据,如上所示

关于分页

  • 设定分页参数后,CRL会生成对应数据库分页语法,如MSSQL采用ROWNUM分页
  • 分页默认是编译为存储过程,如果数据库不支持自动编译,由以语句的形式查询
  • 默认分页和Group分页为两种处理方式

更新2:表结构强制检查

关于数据表创建缓存依赖

  1. CRL会自动创建对象对应的表结构,并初始
  2. CRL判断该不该创建对象对应的数据表,是由表缓存文件来判断,缓存文件路径/config/TableCache.config
  3. 系统运行时检查目录内有没有缓存,有则加载,没有则创建,在CRL内部检测表创建方法内,根据此缓存来判断,不存在表缓存,则创建表并保存缓存值
  4. 新增的对象,此时缓存内是没有的,则会创建数据表
  5. 在缓存结构和数据表结构一致的情况下,新增对象属性时,会自动创建数据表列
  6. 缓存文件和数据库实际表结构在一些情况下可能不一致,则需要手动干预
  • 当数据库有表,但字段不全,也没有缓存文件,CRL创建缓存文件时会按对象完整的结构缓存,此时缓存的表结构和数据库结构就不一致
  • 当缓存内有表,数据库没有表,CRL没法判断,不会自动创建表
  • 当缓存内表有所有表字段结构,数据库表字段被手动删掉,此时结构不一致
  • 当缓存文件被其它数据源生成的缓存文件覆盖了,可能产生结构不一致

由于以上问题,可能会导至找不到字段或表的错误,当前版本作了完善,于是在后台单独开启了一个线程,用以检查表结构,在对象被首次访问后,就会添加到结构检查队列,由后台异步进行处理

在程序运行后,每个被访问过的对象会被检查一次结构,达到结构同步的目的

3.0增新的演示项目CRLShoppingDemo

之前有人提到看不懂文档,希望有简单的例子,如你所愿,按基本在线销售系统写了一个Demo,以下为运行效果

CRL快速开发框架开源完全转到Github

此演示项目正如上面所说,采用了精简的写法实现了这些业务

CRL快速开发框架开源完全转到Github

继承业务封装,实现会员管理

 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;
}

更多详细写法请对照示例和开发文档

增加了测试类WebTest.Code.TestAll.cs

此类演示了所有查询方式,在调用通过的情况下,达到集成测试的结果

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 => < b.Id);//不再区分左边右边了
query.Where(b => b.Id < b.Number);//直接比较可以解析通过
query.Where(b => b.ProductName.Contains(""));//包含字符串
query.Where(b => !b.ProductName.Contains(""));//不包含字符串
query.Where(b => b.ProductName.In("", ""));//string in
query.Where(b => b.AddTime.Between(DateTime.Now, DateTime.Now));//在时间段内
query.Where(b => b.AddTime.DateDiff(DatePart.dd, DateTime.Now) > );//时间比较
query.Where(b => b.ProductName.Substring(, ) == "");//截取字符串
query.Where(b => b.Id.In(, , ));//in
query.Where(b => !b.Id.In(, , ));//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(, ));//数字区间
query.Where(b => b.ProductName.Like(""));// %like%
query.Where(b => b.ProductName.LikeLeft(""));// %like
query.Where(b => b.ProductName.LikeRight(""));// like%
query.Page(, );
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(""))
.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(""))
.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(""))
.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 == "" && b.Name == "");
var sql2 = query.PrintQuery();
#endregion #region GROUP
query = Code.ProductDataManage.Instance.GetLambdaQuery();
query.Where(b => b.Id > );
//选择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() >= );
//设置排序
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 > );
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 > , b => b.Number * b.UserId);
//按条件id>0,进行总计
var count = instance.Count(b => b.Id > );
var max = instance.Max(b => b.Id > , b => b.Id);
var min = instance.Min(b => b.Id > , 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 == , c);
//按对象差异更新
var p = new Code.ProductData() { Id = };
//手动修改值时,指定修改属性以在Update时识别,分以下几种形式
p.Change(b => b.BarCode);//表示值被更改了
p.Change(b => b.BarCode, "");//通过参数赋值
p.Change(b => b.BarCode == "");//通过表达式赋值
Code.ProductDataManage.Instance.Update(b => b.Id == , p);//指定查询更新 p = Code.ProductDataManage.Instance.QueryItem(b => b.Id > );
p.UserId += ;
Code.ProductDataManage.Instance.Update(p);//按主键更新,主键值是必须的
#endregion #region 缓存更新
var item = Code.ProductDataManage.Instance.QueryItemFromCache();
var guid = Guid.NewGuid().ToString().Substring(,);
item.Change(b => b.SupplierName, guid);
Code.ProductDataManage.Instance.Update(item);
item = Code.ProductDataManage.Instance.QueryItemFromCache();
var item2 = Code.ProductDataManage.Instance.QueryItem();
var a = item.SupplierName == item2.SupplierName && item.SupplierName == guid;
if (!a)
{
throw new Exception("更新缓存失败");
}
#endregion #region 事务
string error;
item = Code.ProductDataManage.Instance.QueryItem(); var result = Code.ProductDataManage.Instance.PackageTrans((out string ex) =>
{
ex = "";
var product = new ProductData();
product.BarCode = "sdfsdf";
product.Number = ;
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------------------------->开发&测试文档

CRL快速开发框架开源完全转到Github的更多相关文章

  1. 非关系型数据库来了&comma;CRL快速开发框架升级到版本4

    *?,我很任性,我要造不一样的*,同时支持关系型和非关系型的框架有没有 新版数据查询作了些调整,抽象了LabmdaQueryy和DBExtend,升级到版本4,非关系数据库MongoDB被支持了! ...

  2. CRL快速开发框架系列教程十三&lpar;嵌套查询&rpar;

    本系列目录 CRL快速开发框架系列教程一(Code First数据表不需再关心) CRL快速开发框架系列教程二(基于Lambda表达式查询) CRL快速开发框架系列教程三(更新数据) CRL快速开发框 ...

  3. CRL快速开发框架系列教程十二&lpar;MongoDB支持&rpar;

    本系列目录 CRL快速开发框架系列教程一(Code First数据表不需再关心) CRL快速开发框架系列教程二(基于Lambda表达式查询) CRL快速开发框架系列教程三(更新数据) CRL快速开发框 ...

  4. CRL快速开发框架系列教程十一&lpar;大数据分库分表解决方案&rpar;

    本系列目录 CRL快速开发框架系列教程一(Code First数据表不需再关心) CRL快速开发框架系列教程二(基于Lambda表达式查询) CRL快速开发框架系列教程三(更新数据) CRL快速开发框 ...

  5. CRL快速开发框架系列教程十&lpar;导出对象结构&rpar;

    本系列目录 CRL快速开发框架系列教程一(Code First数据表不需再关心) CRL快速开发框架系列教程二(基于Lambda表达式查询) CRL快速开发框架系列教程三(更新数据) CRL快速开发框 ...

  6. CRL快速开发框架系列教程九&lpar;导入&sol;导出数据&rpar;

    本系列目录 CRL快速开发框架系列教程一(Code First数据表不需再关心) CRL快速开发框架系列教程二(基于Lambda表达式查询) CRL快速开发框架系列教程三(更新数据) CRL快速开发框 ...

  7. CRL快速开发框架系列教程七&lpar;使用事务&rpar;

    本系列目录 CRL快速开发框架系列教程一(Code First数据表不需再关心) CRL快速开发框架系列教程二(基于Lambda表达式查询) CRL快速开发框架系列教程三(更新数据) CRL快速开发框 ...

  8. CRL快速开发框架系列教程六&lpar;分布式缓存解决方案&rpar;

    本系列目录 CRL快速开发框架系列教程一(Code First数据表不需再关心) CRL快速开发框架系列教程二(基于Lambda表达式查询) CRL快速开发框架系列教程三(更新数据) CRL快速开发框 ...

  9. CRL快速开发框架系列教程五&lpar;使用缓存&rpar;

    本系列目录 CRL快速开发框架系列教程一(Code First数据表不需再关心) CRL快速开发框架系列教程二(基于Lambda表达式查询) CRL快速开发框架系列教程三(更新数据) CRL快速开发框 ...

随机推荐

  1. POJ 3683 Priest John&&num;39&semi;s Busiest Day &lpar;2-SAT&rpar;

    题意:有n对新人要在同一天结婚.结婚时间为Ti到Di,这里有时长为Si的一个仪式需要神父出席.神父可以在Ti-(Ti+Si)这段时间出席也可以在(Di-Si)-Si这段时间.问神父能否出席所有仪式,如 ...

  2. 安装concrete时提示&OpenCurlyDoubleQuote;&period;&period;&period;database does not support InnoDB database tables&period;&period;&period;&quot&semi;如何解决

    安装很多系统时,经常有有提示: "...database does not support InnoDB database tables..." 解决办法: 找到MySQL的配置文 ...

  3. 二叉树的遍历&lpar;递归,迭代,Morris遍历)

    二叉树的遍历: 先序,中序,后序: 二叉树的遍历有三种常见的方法, 最简单的实现就是递归调用, 另外就是飞递归的迭代调用, 最后还有O(1)空间的morris遍历: 二叉树的结构定义: struct ...

  4. Trie树模板~~~

    * + ; ; // 字母表为全体小写字母的Trie struct Trie { int ch[maxnode][sigma_size]; int val[maxnode]; int sz; // 结 ...

  5. 数据持久化之SP的优化—送工具类

    第一点:sp存储的是键值对 getSharedPreferences 第一个參数是你保存文件的名字,第个是保存的模式一般能够默觉得0 先看普通 使用SP 存储String类型字符串吧 SharedPr ...

  6. windows下使用Git Bash命令行克隆远程仓库代码

    此处使用的代码托管平台是GitLab,相比GitHub来说,它可以设置免费的私有仓库,哈哈,妈妈再也不用担心我的源码泄露了!1.切换到本地的工作目录,我的目录是: cd /d/coder/websit ...

  7. android 资源文字ids的作用

    ids.xml--为应用的相关资源提供唯一的资源id.id是为了获得xml中的对象而需要的参数,也就是Object = findViewById(R.id.id_name)中的id_name.这些值可 ...

  8. JS实现排序算法

    代码如下: 1.冒泡排序 <script> var arr = [9, 8, 7, 5, 7, 1, 45, 12, 7, 74, 4]; for (var i = 0; i < a ...

  9. JavaSE&lowbar;坚持读源码&lowbar;HashSet对象&lowbar;Java1&period;7

    对于 HashSet 而言,它是基于 HashMap 实现的,HashSet 底层采用 HashMap 来保存所有元素,因此 HashSet 的实现比较简单,查看 HashSet 的源代码,可以看到如 ...

  10. JavaScript学习之路-为什么要学习JavaScript语法

    版权声明:未经博主允许不得转载 前言 为什么要学习JavaScript语法,没有理由,因为工作需要,也为了成为全栈,那现在还是好好努力学习吧! 发展 说实话,JavaScript很好学也很重要,也很容 ...