zoukankan      html  css  js  c++  java
  • Entity Framework学习笔记(六)----使用Lambda查询Entity Framework(1)

    请注明转载地址:http://www.cnblogs.com/arhat

    在前几章中,老魏一直使用Linq来查询Entity Framework。但是老魏感觉,如果使用Linq的话,那么Linq的返回值类型有的时候不是很容易找出来,没有直接使用Lambda来的直观,至少在Lambda中我们可以指定返回的类型,这样一来就可以指定返回值了。

    在本章的开始呢,老魏先复习一下.NET提供的几个常用的Lambda委托,而这些委托可以说是经常又得到的,尤其实在IEnumerable<T>和 IQueryable<T>的扩展方法中经常的被用到。

    常用委托:

    1.封装一个具有一个参数并返回 TResult 参数指定的类型值的方法。

    public delegate TResult Func<in T, out TResult>(T arg)

    这个委托有两个类型参数,一个输入参数和返回值:
    in T:此委托封装的方法的参数类型。
    out TResult:此委托封装的方法的返回值类型。
    那么这个委托怎么用呢?

    Func<int,int> f = a=>{return a+1;};
        int b = f(1);

    结果b=2

    2.封装一个具有两个参数并返回 TResult 参数指定的类型值的方法。

    public delegate TResult Func<in T1, in T2, out TResult>(T1 arg1,T2 arg2)

    这个委托有3个类型参数,两个输入参数和返回值:
    in T1:此委托封装的方法的第一个参数类型。
    in T2:此委托封装的方法的第二个参数类型。
    out TResult:此委托封装的方法的返回值类型
    那么这个委托怎么用呢?

    Func<int,int,int> f = (a,b)=>{return a+b;}
       int b = f(1,2);

    结果b=3

    Func<int,int,bool> f1 = (a,b)=>{
    
           if(a==b){
    
                 return true;
    
           }else{
    
                 return false;
    
           }
    
    };
    bool b = f1(1,2);

    结果:b=false

    有了这两个委托后,下面就可以来研究一下IQueryable< T> 接口的扩展方法了,这些扩展方法基本上就是围绕着这两个委托来进行的。

    首先我们来看看Where的扩展方法,这个扩展方被重载了四次,但是由于在Ling To Entity中,有二个重载方法不被支持,所以这里就不在对这二个重载函数进行讲解了。

    wps_clip_image-3231

    从图上可以看到有四个重载方法,但是对于类型是Expression参数类型的是专门针对Entity Framework的,所以对与没有Expression参数的方法是从IEnumerable<T>中继承过来的。而对于Func<TSource,Int32,Boolean>类型参数的方法是不被Entity Framework支持的。

    下面我们主要来看看这个方法:

    public static IQueryable<TSource> Where<TSource>(
    
        this IQueryable<TSource> source,
    
        Expression<Func<TSource, bool>> predicate
    
    )

    类型参数

    TSource

    source 中的元素的类型。

    参数

    source

    类型: System.Linq.IQueryable<TSource>

    要筛选的 IQueryable<T>。

    predicate

    类型: System.Linq.Expressions.Expression<Func<TSource, Boolean>>

    用于测试每个元素是否满足条件的函数。

    返回值

    类型: System.Linq.IQueryable<TSource>

    一个 IQueryable<T>,包含满足由predicate 指定的条件的输入序列中的元素。

    需要注意的是凡是实现IQueryable<T>的类基本上都是一个集合类,所以这个参数是判断集合中的每个元素是否满足条件的,所以这个委托的输入参数类型是TSource就是集和中的元素类型,如果这个元素满足条件,则返回一个bool值。

    Demo:

    List<string> list = new List<string>{“aa”,”bb”,”cccc”,”ff”};
    
       IQueryable<string> query=list.Where<string>(a=>a.Length>3);

    当list调用where方法的时候,由于list中存放的元素类型是string所以where的输类型参数也是string,然后看一下输入参数Func<string,bool>,这个委托是用于判断list集合中每个元素的表达式,当满足条件的时候会把这个元素放入一个临时集合中,一直到吧list中所有元素都判断完毕之后,那么临时集合中存放的就是满足条件的元素,然后把这临时的集合返回出去赋值给IEnumrable<string>

    下面我们来模拟一下这个where方法的原理:

    where<string>(Expresssion<Func<TSource, bool>> predicate)
    
      {
    
             IQueryable<string> result = new List<string>();
    
             foreach(string str in this)
    
            {
    
                if(predicate(str))
    
                {
    
                    list.Add(str);
    
                }
    
            }
    
         return result;
    
    }

    当把predicate = a=>{return a.Length>3;}传递给这个函数的时候,在函数的if语句中就会循环的判断这个集合中的元素,把满足的元素添加到临时的list中,最后返回。

    下面我们来看看Select方法:

    wps_clip_image-6565

    从图上可以看出,这个方法也是重载了4次,齐总Expression是针对Entity Framework的,但是参数Func<TSourse,Int32,TResult>是不被支持的。看到这里的时候,我们会非常的郁闷,Where方法和Select方法都有一个Expression参数的方法,但是Expression是什么,和没有Expression的方法有什么区别吗?其实这是微软对Entity Framework做的一个优化,Expression是“表达式树”,通过Expression可以吧表达式嵌入到SQL语句中形成一个优化的SQL,而没有Expression的方法,不会生成优化的SQL语句,在网上大家可以看看Func<TSource,TResult>陷阱的文章。所以呢,这里我们推荐使用的是Expression类型的表达式树。

    public static IQueryable<TResult> Select<TSource, TResult>(
    
        this IQueryable<TSource> source,
    
        Expression<Func<TSource, TResult>> selector
    
    )

    TSource

    source 中的元素的类型。

    TResult

    由 selector 表示的函数返回的值类型。

    参数

    source

    类型: System.Linq.  IQueryable<  TSource> 
    一个要投影的值序列。

    selector

    类型: System.Linq.Expressions.  ExpressionFunc<  TSource, TResult>  > 
    要应用于每个元素的投影函数。

    返回值

    类型: System.Linq.  IQueryable<  TResult> 
    一个 IQueryable<  T> ,其元素为对source 的每个元素调用投影函数的结果。

    List<Student> list = new List<Student>()
    
    {
    
          new Student(){SId=1,SName="济公",SAge=56,SSex="",CId=1},
    
          new Student(){SId=2,SName="飞龙僧",SAge=25,SSex="",CId=2},
    
          new Student(){SId=3,SName="刘太真",SAge=34,SSex="",CId=2},
    
          new Student(){SId=4,SName="玉面仙姑",SAge=78,SSex="",CId=1},
    
          new Student(){SId=5,SName="东方太悦",SAge=90,SSex="",CId=3},
    
          new Student(){SId=6,SName="无语老祖",SAge=123,SSex="",CId=3},
    
          new Student(){SId=7,SName="黄淑女",SAge=23,SSex="",CId=2}
    
    };
    
    IQueryable<string> query = list.Select<Student, string>(student => student.SName);
    
    foreach (string name in query)
     {
         Console.WriteLine(name);
    }

    在使用select方法的时候,指定了集合中的元素类型和返回值中的元素类型。其中要查询的集合元素类型为Student,而返回值的类型是string。所在在lambda中我们指定返回student.SName类型。

    当然了,我们还可以指定多个列。代码如下:

    IQueryable<List<string>> query = list.Select<Student, List<string>>(student => { return new List<string> { student.SName, student.SAge + "" }; });
    
       foreach (List<string> row  in query)
    
       {
    
             Console.WriteLine(row[0] + "  " + row[1]);
    
       }

    在这个方法中,我们指定了返回的类型是List<string>。所以在Lambda中我们创建了一个List<string>对象,用于保存每个元素的SName,SAge两个属性。这里需要注意的是在List<student>中的每个元素的SName,SAge都是一个List<string>。

    本章就写到这里吧,本章之讲解了Where和Select两个扩展方法,东西不多,但是对于那些还停留在入门的朋友来说,可以作为参考文章。那么在接下来的文章中,老魏还会继续探讨一下这些常用的扩展方法,并通过实例来显示这些方法在Entity Framework中怎么使用。希望能给大家带来帮助!顺便这里老魏说一下,发表文章的时间还是不确定,因为时间有限,所以只能在闲暇的时间来写文章了。

  • 相关阅读:
    OI数学知识清单
    线段树入门教程
    扩展欧几里得定理基础讲解 代码及证明
    名字竞技场 V3.0
    可持久化线段树(主席树)新手向教程
    矩阵乘法浅析
    [Luogu] P1233 木棍加工
    高斯消元 模板
    位运算技巧
    [ZJOJ] 5794 2018.08.10【2018提高组】模拟A组&省选 旅行
  • 原文地址:https://www.cnblogs.com/arhat/p/3665144.html
Copyright © 2011-2022 走看看