LINQ统一数据操作语句

来源:互联网 发布:centos 6.5配置双ip 编辑:程序博客网 时间:2024/05/08 03:36

一、基本原理

1.数据源无关的数据统一操作,LINQ语句做了一个程序语句到各种数据源之间的抽象统一中间件。where开始,select或group结束. order 和group,select new等各种语句
2.用了拓展方法,在generic枚举类型来做,编译器会将LINQ语句解释为where上的枚举类型的事例对象上调用拓展方法,实现功能。因为拓展方法的拓展接口是IEnumerable所以所有继承该接口的实现类都支持该拓展方法。
    不是所有的数据筛选都可以用预定义的拓展方法LINQ来表示,所以有时候要自己定义LINQ函数和拓展方法;拓展方法工作方式是直接from r in语句活得数据源结构对象集合调用where方法,返回结果集再调用select或者group方法;LINQ运算顺序都是从左到右的,如果嵌套的from语句那么外部和内部将有两个传入参数作为selectmany的输入,提供一个内部的类型作为约束,外部的类型输出和继续使用后面的约束。
3. 用了枚举器来做,LINQ只是定义遇到yield return标记返回不执行,foreach才执行yield return执行下去,转换为其它容器或ToLookup时候会立即执行。但是注意中间数据结构元素的变化会迭代出不同的结果,如果最后用了Tolist等就不会等到迭代时才返回集合。
    LINQ上的操作,where选定数据集,数据查找筛选,逻辑表达式和比较表达式支持,开始偏移和截取长度搜索个数,前面开始后面开始搜索,排序,分组,数据连接外部内部,集合操作,聚合函数,视图集合转换产生,判断是否满足条件的函数。

二、LINQ数据处理应用

1).筛选from 嵌套from
2).排序orderby语句,以及和 thenby多个组合语句。
3).分组group,group r by r.x into 别名 。是用groupby拓展方法来进行分组。
select new可以从分组的结果里面再创建新的统计结果。
4).连接jiont操作
5).集合操作交并差,可以将查询语句封装为方法或limban表达式.
6).zip(),take(),skip()方法。
7).聚合函数
8).转换为其它容器, 查询会在迭代时候执行,而转换为容器时候却会立即执行。
ToLookup函数和非类型化的集合上使用LINQ就可以用Cast()方法作为转换。
9)Range,Empty,Repeat()不是拓展方法,而是集合类的正常静态方法,也会推迟执行,基于原来类型构建迭代器。
具体多查询资料和实践编程。

三、并行查询

在.net 4.0后增加的,通过System.Linq中的新类,ParallelEnumerable可以分解查询工作到多个线程中,ParallelEnumerable大多数拓展方法是ParallelQuery<TSource>的拓展,一个例外是AsParallel()方法它拓展了IEnumerable<TSource>接口,返回ParallelQuery<TSource>类,所以正常集合可以并行方式查询。
应用:1)正常查询用容器上containerName.AsParallel()方法,那么所有的where,select,sum都会变成Parallel版本的。
2)Partitioner.Create(containerName,true).AsParallel()来并行查询。
3)取消,调用WithCancellation方法,且传递一个CancellationToken作为令牌参数创建,需要调用时候用令牌Cancel()就可以了,例如:
例如:
static void Main()        {            // IntroParallel();            Cancellation();        }        static void Cancellation()        {            const int arraySize = 100000000;            var data = new int[arraySize];            var r = new Random();            for (int i = 0; i < arraySize; i++)            {                data[i] = r.Next(40);            }            var cts = new CancellationTokenSource();            new Thread(() =>                {                    try                    {                        var sum = (from x in data.AsParallel().WithCancellation(cts.Token)                                   where x < 80                                   select x).Sum();                        Console.WriteLine("query finished, sum: {0}", sum);                    }                    catch (OperationCanceledException ex)                    {                        Console.WriteLine(ex.Message);                    }                }).Start();            Console.WriteLine("query started");            Console.Write("cancel? ");            int input = Console.Read();            if (input == 'Y' || input == 'y')            {                // cancel!                cts.Cancel();            }        }        static void IntroParallel()        {            const int arraySize = 100000000;            var data = new int[arraySize];            var r = new Random();            for (int i = 0; i < arraySize; i++)   {       data[i] = r.Next(40);   }            Stopwatch watch = new Stopwatch();            watch.Start();                        var q1 = (from x in Partitioner.Create(data).AsParallel()                      where x < 80                     select x).Sum();            watch.Stop();            Console.WriteLine(watch.ElapsedMilliseconds);        }    }

四、表达式树

表达式树是一个可以改变语义分析的编译器级别的功能,也就是可以为编写的不同的表达式语句,定义不同的执行函数。
通过树形结构来调用不同的处理函数。
例如:lambda表达式可以用于委托中,也可以用于Expression类型中作为参数,Expression有很多表达式的类型派生类,可以分析执行表达式,例如:
class Program    {        private static void DisplayTree(int indent, string message, Expression expression)        {            string output = String.Format("{0} {1} ! NodeType: {2}; Expr: {3} ",                  "".PadLeft(indent, '>'), message, expression.NodeType, expression);            indent++;            switch (expression.NodeType)            {                case ExpressionType.Lambda:                    Console.WriteLine(output);                    LambdaExpression lambdaExpr = (LambdaExpression)expression;                    foreach (var parameter in lambdaExpr.Parameters)                    {                        DisplayTree(indent, "Parameter", parameter);                    }                    DisplayTree(indent, "Body", lambdaExpr.Body);                    break;                case ExpressionType.Constant:                    ConstantExpression constExpr = (ConstantExpression)expression;                    Console.WriteLine("{0} Const Value: {1}", output, constExpr.Value);                    break;                case ExpressionType.Parameter:                    ParameterExpression paramExpr = (ParameterExpression)expression;                    Console.WriteLine("{0} Param Type: {1}", output, paramExpr.Type.Name);                    break;                case ExpressionType.Equal:                case ExpressionType.AndAlso:                case ExpressionType.GreaterThan:                    BinaryExpression binExpr = (BinaryExpression)expression;                    if (binExpr.Method != null)                    {                        Console.WriteLine("{0} Method: {1}", output, binExpr.Method.Name);                    }                    else                    {                        Console.WriteLine(output);                    }                    DisplayTree(indent, "Left", binExpr.Left);                    DisplayTree(indent, "Right", binExpr.Right);                    break;                case ExpressionType.MemberAccess:                    MemberExpression memberExpr = (MemberExpression)expression;                    Console.WriteLine("{0} Member Name: {1}, Type: {2}", output,                       memberExpr.Member.Name, memberExpr.Type.Name);                    DisplayTree(indent, "Member Expr", memberExpr.Expression);                    break;                default:                    Console.WriteLine();                    Console.WriteLine("{0} {1}", expression.NodeType, expression.Type.Name);                    break;            }        }        static void Main()        {            Expression<Func<Racer, bool>> expression = r => r.Country == "Brazil" && r.Wins > 6;            DisplayTree(0, "Lambda", expression);        }    }

上述是lambda表达式用于Expression类型。
LINQ TO SQL中lambda表达式用于Expression<T>类型。
也可以定义自己的Expression<T>拓展方法类型和LINQ表达式,实现自己的表达式树,这样表达式树存在于程序集中,执行的时候会读取。

五、LINQ提供程序

LINQ语句.net框架中定义的目标对象有:LINQ to Objects, LINQ to XML,LINQ to SQL。
其中LINQ语句具体的解释由作用的数据源容器类型来决定。
例如LINQ to Objects中的Whered拓展方法定义为:
public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource>s source, Func<TSource, bool> predicate);
LINQ to SQL中的where拓展方法定义为:
public static IQueryable<TSource> Where<TSource>(this IQueryable<TSource> source, Expression<Func<TSource,bool>> predicate);
当在SQL中的where语句时候,因为作用的容器数据源类型是ADO中定义的ObjectContext类的CreateQuery<T>()方法返回一个实现了IQueryable<TSource>接口的ObjectQuery<T>对象,因此时候使用Queryable类的Where()方法。
LINQ 是比较深奥的主题,主要是用到了表达式树的函数式语言的编程思想,拓展方法拓展当前的数据源自定义拓展方法,数据源上进行数据的操作会创建各种类型的容器和需要的委托方法(lambda表达式),以及对各种数据源底层细节的封装对上层提供了统一的LINQ简易数据操作。


0 0
原创粉丝点击