前言:
继上一版本:CYQ.Data 数据框架 版本发布 V4.5,刷的一下又三个多月了,
进一步的说,从 CYQ.Data V4.5的发布到现在,是半年多了,今天,终于得发布新小版本了。
由于上一版本过于稳定,导致此版本无bug修正项,但是新增了几个重要的性能优化功能。
本版本新增加的功能预览
1:优化Access、SQLite数据库链接,以{0}代表根目录
好处:可以配置多个数据库链接,示例如:秋色园QBlog同时用了N个access数据库。
2:MAction增加指定列的查询功能:SetSelectColumns
好处:查询时可以指定列名,减少传输量。
3:增加AppDebug类,可以全局输出执行过的SQL语句
好处:随时掌控并打印页面SQL,直接分析和优化SQL语句
4:增加FastToT的Emit类,提升大数据量时从MDataTable转List<T>的性能
好处:在返回数据量较大转实体时,可以利用Emit加快速度,提升性能。
5:关闭默认mssql/oracle的事务开启
好处:事务有需要就打开,默认不打开。
如需要兼容V4.5及以前版本的事务,可使用配置项兼容:<add key="TransationDefaultOpen" value="true"> </add>
6:XmlHelper更名为XHtmlAction
其它:增加的配置项:
OpenDebugInfo:true/false,是否开启调试SQL语句记录,开发时打开,运行时可关闭。
RecordSqlLongQueryTime:N(单位毫秒),运行时设置,记录执行时间长的SQL语句,可以针对性分析与优化。
AppDebugFilterTime:N(单位毫秒),AppDebug可以输出页面SQL,通过此项可以过滤。
下面进行详细的解说
1:优化Access、SQLite数据库链接,以{0}代表根目录
示例:
<add name="Conn" connectionString="Data Source={0}App_Data\qblog.db;failifmissing=false" providerName="System.Data.SQLite" />
</connectionStrings>
2:MAction增加指定列的查询功能:SetSelectColumns
示例:[包含:查询,分页,绑定]
{
int count;
using (MAction action = new MAction(TableNames.Blog_Class))
{
action.SetSelectColumns(selectColumns);//指定列
action.Select(Pager1.PageIndex, Pager1.PageSize, string.Empty, out count).Bind(gvClass);
Pager1.Count = count;
Pager1.BindName = "BindData";
}
}
3:增加AppDebug类,可以全局输出执行过的SQL语句
示例:[在页面基类里,轻松处理一下即可]
{
protected override void OnInit(EventArgs e)
{
AppDebug.Start();//开启记录页面的SQL
base.OnInit(e);
}
protected override void OnPreRenderComplete(EventArgs e)
{
base.OnPreRenderComplete(e);
Response.Write(AppDebug.Info);//输出记录页面的SQL
AppDebug.Stop();//停止记录页面的SQL
}
}
页面效果:
4:增加FastToT的Emit类,提升大数据量时从MDataTable转List<T>的性能
这里直接放上我研究N天的源码,不过能看懂的估计也毛毛无几,能用上的直接拿去用了:
using System.Collections.Generic;
using System.Text;
using System.Reflection.Emit;
using System.Reflection;
using CYQ.Data.Table; namespace CYQ.Data.Tool
{
/// <summary>
/// 快速转换类[数据量越大[估约500条起],性能越高]
/// </summary>
internal class FastToT<T>
{
public delegate T EmitHandle(MDataRow row);
/// <summary>
/// 构建一个ORM实体转换器
/// </summary>
/// <typeparam name="T">转换的目标类型</typeparam>
/// <param name="schema">表数据架构</param>
public static EmitHandle Create(MDataTable schema)
{
Type tType = typeof(T);
Type rowType = typeof(MDataRow);
DynamicMethod method = new DynamicMethod("RowToT", tType, new Type[] { rowType }, tType);
MethodInfo getValue
= rowType.GetMethod("GetItemValue", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[] { typeof(int) }, null);ILGenerator gen
= method.GetILGenerator();gen.DeclareLocal(tType);
gen.DeclareLocal(typeof(object));
gen.DeclareLocal(typeof(bool));
gen.Emit(OpCodes.Newobj, tType.GetConstructor(BindingFlags.Instance
| BindingFlags.Public | BindingFlags.NonPublic, null, new Type[] { }, null));gen.Emit(OpCodes.Stloc_0);
int ordinal = -1;
foreach (FieldInfo field in tType.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public))
{
string fieldName = field.Name.TrimStart('_');
ordinal = schema.GetOrdinal(fieldName);
if (ordinal > -1)
{
Label retFalse = gen.DefineLabel();
gen.Emit(OpCodes.Ldarg_0);
gen.Emit(OpCodes.Ldc_I4, ordinal);
gen.Emit(OpCodes.Call, getValue);
gen.Emit(OpCodes.Stloc_1);
gen.Emit(OpCodes.Ldloc_1);
gen.Emit(OpCodes.Ldnull);
gen.Emit(OpCodes.Ceq);
gen.Emit(OpCodes.Stloc_2);
gen.Emit(OpCodes.Ldloc_2);
gen.Emit(OpCodes.Brtrue_S, retFalse);
//为null值,跳过gen.Emit(OpCodes.Ldloc_0);
gen.Emit(OpCodes.Ldloc_1);
EmitCastObj(gen, field.FieldType);
gen.Emit(OpCodes.Stfld, field);
gen.MarkLabel(retFalse);
//继续下一个循环}
}
gen.Emit(OpCodes.Ldloc_0);
gen.Emit(OpCodes.Ret);
return method.CreateDelegate(typeof(EmitHandle)) as EmitHandle;
}
private static void EmitCastObj(ILGenerator il, Type targetType)
{
if (targetType.IsValueType)
{
il.Emit(OpCodes.Unbox_Any, targetType);
}
else
{
il.Emit(OpCodes.Castclass, targetType);
}
}
}
}
其它几点的示例,写成了示例项目:
示例解决方案:
完整的示例页面:
最后:
CYQ.Data 数据框架主页:http://www.cyqdata.com/cyqdata
CYQ.Data 数据框架下载(包括示例):http://www.cyqdata.com/download/article-detail-426
转载请注明:CYQ.Data V4.5.5 版本发布[顺带开源Emit编写的快速反射转实体类FastToT类] | 胖虎的工具箱-编程导航