在项目中想必大家肯定是使用各种ORM, 如:NH、EF、fluent Data。 然而我在使用ORM的这几年中,随着数据库的结构越来越复杂,自定义查询的越来越多,但是一直没有解决一个问题就是自定义查询,每遇到自定义查询时就需要手动建个业务实体来承载自定义查询的结果集。
上周在萧秦的博客中突然发现了一句代码,让我眼前一亮:
class="brush:csharp;gutter:false;">public IEnumerable<dynamic> Get() { //构建查询参数 var pQuery = ParamQuery.Instance() .Select("A.*,B.PermissionName as ParentName") .From(@"sys_permission A left join sys_permission B on B.PermissionCode = A.ParentCode"); //调用服务基类中的共通方法返回查询结果 return service.GetDynamicList(pQuery); }
使用了IEnmuerable<dynamic> 来解决自定义查询的结果集问题,随后我请教了萧秦,他使用的是fluent Data ORM, 这个框架是支持IEnumerable<dynamic>,而EF不支持。 所以在使用自定义查询时: 1、可以创建业务实体来承载结果集。 2、使用dynamic linq来解决,既然ORM不支持,那么使用SqlHelper来返回DataTable,在DataTable的基础上使用dynamic linq来解决,想想如果是做数据管理平台的话,肯定大部分功能都是报表多、查询多,那么这就是个大问题,一个项目组10个人,那么每个人如果都去建几个业务实体,那么Model岂不是很变态。
DataTable dt = GetDataTable(); var query = from p in dt.AsEnumerable() select new { ID=Convert.toInt32(p["StuID"]), Name=p["StuName"].toString(), Chinese=Convert.toInt32(p["Chinese"]) };
最后返回IEnumerable<dynamic>, 在写这个demo时候我先使用ID=p.Field<int>("StuID"), 然后在遍历数据时提示转化无效异常,才采用了p["StuID"]的写法,实际上这时p就是一个DataRow对象。这个过程只是省去了再去创建自定义Model的过程。
完整方法:
public IEnumerable<dynamic> Get() { DataTable dt = GetDataTable(); var query = from p in dt.AsEnumerable() select new { ID=Convert.toInt32(p["StuID"]), Name=p["StuName"].toString(), Chinese=Convert.toInt32(p["Chinese"]) }; return query; }
仅仅是个人工作过程中遇到的问题和自己想出的解决办法,有更好的多谢大家指教。同时猜测微软会不会在以后的版本中升级这个功能呢?