LINQ统一数据操作语句

一、基本原理

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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值