Entity Framework 动态构造select表达式

来源:互联网 发布:java就业培训教程豆瓣 编辑:程序博客网 时间:2024/06/07 16:39

扩展ef自动映射需要查询的字段

比如我们需要返回某些字段会采用如下的写法


但是发现每次都去写select如果字段很多不想去一个一个查询出来,就想指定一个dto的类型

他就能查询dto里边的字段,然后自动映射到dto里边去就可以减少很多工作量了


我们把lambda表达式提到外面去


这种可以,但是下面这种构建一个dto_user怎么都不行要报错



找了很久把表达式变成func就可以了


或者调用表达式树的Compile方法生成func当然也是一样的


有了这个就可以通过类型+反射动态构建查询的字段了

测试的原型


测试成功!很高兴于是去封装了一个通用的扩展方法!


用法:


这样就会自动映射DTO_User了,写出来了还是很激动

但是很快就发现问题了,他居然是查询的全部!,然后那个查询需要字段的他居然是在内存中操作了,

每次都会查询全部字段出来

其实这个扩展方法实现了动态拷贝,可以作为解决这个问题的第二个步骤,把需要的字段查询出来后

在进行动态拷贝,平时进行对象转化的时候也可以直接用


然后测试发现select如果传表达式树他会去解析成sql,他会转换成需要查询的字段sql


从返回的IQueryable接口就知道,他是会生成的sql的,但是如果我们传递的是Func呢


返回的却是IEnumerable,当然是在内存中操作的了,

 数据库查询只有IEnumerable才回执行到数据库
IQueryable只拼接sql 


因为func只能在里边当作方法去执行
而表达式数确可以得到很多东西比如参数返回值什么的
这也是他们的区别



想要真正实现自动映射到DTO,而且只查询的还是那几个字段,那么这里要想办法动态创建表达式树,

不能直接传func


这就需要了解ef内部是怎么解析的这个表达式树,还有表达式树是怎么动态生成的了

表达式树的学习:http://www.cnblogs.com/li-peng/p/3154381.html


这篇文章很好的解决了动态构建表达式树:http://www.cnblogs.com/JimmyZheng/archive/2012/02/23/2364154.html

http://blog.csdn.NET/cauchy8389/article/details/23529857

http://bbs.csdn.net/topics/390790484

http://bbs.csdn.Net/topics/390813750


有没那位大神知道ef内部是怎么解析的,怎么动态的构建这个表达式树很想知道


查了2天资料终于找到解决方案了使用MemberInitExpression就可以动态构建

https://msdn.microsoft.com/zh-cn/library/system.linq.expressions.memberinitexpression.aspx

msdn上面的资料

[csharp] view plain copy
  1. class Animal  
  2. {  
  3.     public string Species {getset;}  
  4.     public int Age {getset;}  
  5. }  
  6.   
  7. public static void CreateMemberInitExpression()  
  8. {  
  9.     System.Linq.Expressions.NewExpression newAnimal =  
  10.         System.Linq.Expressions.Expression.New(typeof(Animal));  
  11.   
  12.     System.Reflection.MemberInfo speciesMember =  
  13.         typeof(Animal).GetMember("Species")[0];  
  14.     System.Reflection.MemberInfo ageMember =  
  15.         typeof(Animal).GetMember("Age")[0];  
  16.   
  17.     // Create a MemberBinding object for each member  
  18.     // that you want to initialize.  
  19.     System.Linq.Expressions.MemberBinding speciesMemberBinding =  
  20.         System.Linq.Expressions.Expression.Bind(  
  21.             speciesMember,  
  22.             System.Linq.Expressions.Expression.Constant("horse"));  
  23.     System.Linq.Expressions.MemberBinding ageMemberBinding =  
  24.         System.Linq.Expressions.Expression.Bind(  
  25.             ageMember,  
  26.             System.Linq.Expressions.Expression.Constant(12));  
  27.   
  28.     // Create a MemberInitExpression that represents initializing  
  29.     // two members of the 'Animal' class.  
  30.     System.Linq.Expressions.MemberInitExpression memberInitExpression =  
  31.         System.Linq.Expressions.Expression.MemberInit(  
  32.             newAnimal,  
  33.             speciesMemberBinding,  
  34.             ageMemberBinding);  
  35.   
  36.     Console.WriteLine(memberInitExpression.ToString());  
  37.   
  38.     // This code produces the following output:  
  39.     //  
  40.     // new Animal() {Species = "horse", Age = 12}  
  41. }  

改进下:使用参数来赋值



原创粉丝点击