C#每日一课(三十八)

40 篇文章 1 订阅

LINQ to ADO.NET
它包含 LINQ to DataSet和LINQ to SQL两个相关技术。
LINQ to DataSet:提供对DataSet、DataTable进行查询
LINQ to SQL:通过LINQ对象模型直接与数据库进行数据交互

  • LINQ to DataSet概述
    DataSet是ADO.NET进行无连接模式数据库访问的关键.
    1.缓存不同数据源中的数据
    2.表示层,与界面控件集成进行数据绑定
    3.中间层,提供保留数据关系形状的缓存并包括快速查询和层次结构导航服务

DataSet,允许应用程序把数据子集从一个或多个数据源导入应用程序空间。从面应用程序可以在内存中操作这些数据,同时保留它的关系形状。

痛点:DataSet查询功能存在限制,对于复杂的情况,必须编写自定义的查询,这会导致应用程序性能以及可维护性都变得低下。

ADO.NET负责把数据读入到DataSet中,LINQ to DataSet查询在DataSet和DataTable对象中缓存的数据。
只有在DataSet有填充值后,才能使用LINQ to DataSet查询DataSet对象。LINQ to DataSet通过使用DataRowExtensions和DataTableExtensions类中的扩展方法可以更快更容易查询DataSet中的数据。

DataTableExtensions类提供的扩展方法把DataTable转化成LINQ可以查询的IEnumerable类型。
DataTableExtensions成员:
AsDataView:创建并返回支持LINQ的DataView对象
AsEnumerable:返回IEnumerable对象,这个对象可以用在LINQ表达式或方法查询中
CopyToDataTable:在给定输入IEnumerable对象的情况下,返回包含DataRow对象副本的DataTable

DataRowExtensions类提供的扩展方法对DataRow字段数据的类化读取和设置。
DataRowExtensions成员:
Field:提供对DataRow中的每个列值的强类型访问
SetField:为DataRow中的指定列设设置一个新值

  • LINQ to SQL概述
    LINQ to SQL是ADO.NET系列技术的一部分,它基于由ADO.NET提供程序模型提供的服务。
    可以把LINQ to SQL代码与现有的ADO.NET应用程序混合使用。
    LINQ to SQL架构在ADO.NET之上,通过ADO.NET进行数据库操作,同时使用LINQ to SQL提供程序实现对象模型和关系数据库模型之间的转换。
    对象关系模型是LINQ to SQL的核心部分,它提供数据库模型和对象模型之间的映射关系。
    LINQ to SQL查询时所用的语法与在LINQ中使用的语法一样,不同的是,查询中引用的对象被映射到数据库中的元素。在应用程序执行期间,通过LINQ to SQL来请求LINQ查询执行。LINQ to SQL支持程序随后把LINQ查询转换成等效的SQL命令,并委托ADO.NET提供程序执行数据库操作。
    ADO.NET提供程序把查询结果作为DataReader返回,然后LINQ to SQL提供程序把ADO.NET结果转换成用户对象的IQueryable集合,并对IQueryable集合进行查询,返回查询结果。
    IQueryable接口是LINQ to SQL中使用到的主要接口,它从IEnumerable继承而来,表示一个可以查询的数据集,可以通过LINQ对其进行查询。

LINQ to DataSet复杂数据查询
LINQ to DataSet的使用通常包含如下步骤:
1.获取DataSet/DataTable数据源:可以通过ADO.NET技术从数据库获取,可以通过XML技术从XML文件获取,也可以从其它形式的数据源获取,甚至是可以在内存中直接创建并填充DataSet/DataTable对象。
2.把DataTable转换成IEnumerable类型:在LINQ to DataSet中,通过DataTableExtensions扩展和AsEnumerable()方法从DataTable获取一个等价的IEnumerable对象
3.使用LINQ语法来编写查询
4.使用查询结果
注意:DataSet本身是DataTable的集合,它可以包含一个或多个DataTable及它们之间的关系。LINQ to DataSet实际是对DataTable进行数据查询,并非对DataSet进行查询。

  • 单表数据查询
    使用DataTable类中AsEnumerable()方法,把DataTablel转成一个类型为IEnumerable的可枚举数据集合
    public static EnumerableRowCollection AsEnumerable(DataTable source);
    从上面这个步骤中,从DataTable中获取的元素类型为DataRow。要进一步访问数据表的记录的具体字段数据,需要使用DataRow的一个扩展方泛型方法,Field()方法,来获取DataRow的某个字段的数据
    Field()最常用的重载版本:
    public static T Field(DataRow row,DataColumn column);
    public static T Field(DataRow row,int columnIndex);
    public static T Field(DataRow row,string columnName);
    column:表示数据列要返回数据的字段
    columnIndex:表示从0开始的索引列索引。
    columnName:表示要返回数据的字段的名称。

使用Visual Studio新建C#控制台应用程序
添加一个方法用来创建DataSet

//创建一个包含数据的DataSet
        static DataSet BuildOneDTDataSet()
        {
            string[] nameSet = { "王霞", "张三", "李四", "李花", "王五", "陆六", "夏七", "吴八" };
            string[] sexSet = { "女", "男", "男", "女", "男", "男", "男", "男" };
            int[] ageSet = { 18, 20, 21, 22, 19, 20, 25, 24 };
            //创建一个DataSet对象 PeopleDS
            DataSet ds = new DataSet("PeopleDS");
            //创建一个DataTable对象 PeopleDT
            DataTable dt = new DataTable("PeopleDT");
            //把数据表dt添加到数据集ds当中
            ds.Tables.Add(dt);
            //设置数据表dt中各字段的信息
            dt.Columns.AddRange(new DataColumn[]
            {
                new DataColumn("Name",Type.GetType("System.String")),
                new DataColumn("Sex",Type.GetType("System.String")),
                new DataColumn("Age",Type.GetType("System.Int32"))
            });

            //对于上面已建立的结果,添加相关的数据表信息
            for (int i = 0; i < nameSet.Length; i++)
            {
                //新增行数据
                DataRow row = dt.NewRow();
                row["Name"] = nameSet[i];
                row["Sex"] = sexSet[i];
                row["Age"] = ageSet[i];
                //数据表中添加数据
                dt.Rows.Add(row);
            }
            return ds;
        }

添加一个查询方法:

static void UseSelect()
        {
            //初始化一个数据集ds
            DataSet ds = BuildOneDTDataSet();
            //从ds数据集中获取指定的数据表
            DataTable dt = ds.Tables["PeopleDT"];
            //查询出所有的员
            var query =
                from p in dt.AsEnumerable()
                select p;
            foreach (var item in query)
            {
                Console.WriteLine("Name:{0}\tSex:{1}\tAge:{2}",
                    item.Field<string>("Name"),
                    item.Field<string>("Sex"),
                    item.Field<int>("Age"));
            }

            //查询某个单独元素
            string str = "";    //等查询的是哪列,由用户指定
            Console.Write("请输入要查询的数据:");
            while (true)
            {
                string tmp = Console.ReadLine();
                if (tmp.Equals("Name") || tmp.Equals("Sex") || tmp.Equals("Age"))
                {
                    str = tmp;
                    break;
                }
                else
                {
                    Console.Write("Error!请重新输入需要查询的列:");
                    continue;
                }
            }
            
            var query1 =
                from p1 in dt.AsEnumerable()
                select p1.Field<string>(str);
            Console.WriteLine("根据 " + str + " 查询结果为:");
            foreach (var item in query1)
            {
                Console.Write("{0} ",item);
            }
            Console.WriteLine();
        }

在工程中的Main方法中添加如下代码进行测试:

UseSelect();
Console.ReadKey();

编译运行后结果如下:
运行结果

除了使用select语句外,还要以对DataTable记录进行where过滤,对查询结果进行排序
在工程中添加如下方法:

static void SelectAll()
        {
            DataSet ds = BuildOneDTDataSet();
            DataTable dt = ds.Tables["PeopleDT"];
            Stopwatch swatch = new Stopwatch();
            swatch.Start();
            var query =
                from p in dt.AsEnumerable()
                select p;
            Console.WriteLine("查询所有数据:");
            foreach (var p in query)
            {
                Console.WriteLine("Name:{0}\tSex:{1}\tAge:{2}",
                    p.Field<string>("Name"),
                    p.Field<string>("Sex"),
                    p.Field<int>("Age"));
            }
            swatch.Stop();
            Console.WriteLine("执行耗时:{0}毫秒", swatch.ElapsedMilliseconds.ToString());
        }
        
        static void UseOrderbByWhere()
        {
            //获取数据集ds
            DataSet ds = BuildOneDTDataSet();
            //获取数据集ds中的表格PeopleDT的数据表 dt
            DataTable dt = ds.Tables["PeopleDT"];
            Stopwatch swatch = new Stopwatch();
            swatch.Start();
            //查询数据表中年龄大于20岁的,并且按年龄进行从低到高排序
            var query =
                from p in dt.AsEnumerable()
                orderby p.Field<int>("Age")
                where p.Field<int>("Age") > 20
                select p;
            Console.WriteLine("查询年龄大于20,并按年龄进行从低到高排序:");
            foreach (var p in query)
            {
                Console.WriteLine("Name:{0}\tSex:{1}\tAge:{2}",
                    p.Field<string>("Name"),
                    p.Field<string>("Sex"),
                    p.Field<int>("Age"));
            }
            swatch.Stop();
            Console.WriteLine("执行耗时:{0}毫秒", swatch.ElapsedMilliseconds.ToString());
        }

在Main方法中使用如下代码进行测试:

//查询所有数据
SelectAll();
//按条件查询并做排序
UseOrderbByWhere();
Console.ReadKey();

编译运行的结果如下:
运行结果

使用LINQ to DataSet查询DataTable的数据可以分为两个部分:
1.把DataTable转换成为IEnumerable数据集合,这里使用AsEnumerable()方法
2.对IEnumerable进行操作

  • 多表数据查询
    一个数据订DataSet中一般来说会包含多个数据表DataTable,而且数据表之间有一定的关联关系,从而表示一个关系型数据库。
    通过LINQ to DataSet可以查询多个数据表中的数据,这个时候需要使用多个from子句进行复合查询,同时使用where子句来进行多表之间的关系判断。

使用Visual Studio新增C#控制台应用程序
创建DataSet方法如下:

static DataSet BuildDataSet()
        {
            DataSet ds = new DataSet("StudyInfo");
            //创建StudyInfo的数据表 Student
            DataTable StudentDt = new DataTable("Student");
            ds.Tables.Add(StudentDt);
            //学生信息数据列
            StudentDt.Columns.AddRange(new DataColumn[] {
                new DataColumn("StudentID",Type.GetType("System.String")),
                new DataColumn("StudentName",Type.GetType("System.String")),
                new DataColumn("StudentSex",Type.GetType("System.String")),
                new DataColumn("StudentAge",Type.GetType("System.Int32"))
            });
            //把学生信息添加到数据表
            StudentDt.Rows.Add("00001", "张无忌", "男", 20);
            StudentDt.Rows.Add("00002", "乔峰", "男", 19);
            StudentDt.Rows.Add("00003", "杨霞", "女", 21);
            StudentDt.Rows.Add("00004", "赵敏", "女", 22);
            StudentDt.Rows.Add("00005", "郭靖", "男", 18);

            //创建StudyInfo的数据表 Score
            DataTable ScoreDt = new DataTable("Score");
            ds.Tables.Add(ScoreDt);
            //成绩信息数据列
            ScoreDt.Columns.AddRange(new DataColumn[] {
                new DataColumn("ScoreID",Type.GetType("System.String")),
                new DataColumn("Math",Type.GetType("System.Double")),
                new DataColumn("Chinese",Type.GetType("System.Double")),
                new DataColumn("English",Type.GetType("System.Double"))
            });
            //把成绩信息添加到数据表
            ScoreDt.Rows.Add("001",80.5,75.5,78.0);
            ScoreDt.Rows.Add("002", 88.5, 80.5, 60.0);
            ScoreDt.Rows.Add("003", 75.0, 90.5, 80.0);
            ScoreDt.Rows.Add("004", 59.5, 80.5, 75.0);

            //创建StudyInfo的数据表 StudentScore
            DataTable StuScoreDt = new DataTable("StudentScore");
            ds.Tables.Add(StuScoreDt);
            //学生成绩信息数据列
            StuScoreDt.Columns.AddRange(new DataColumn[] {
                new DataColumn("StudentScoreID",Type.GetType("System.String")),
                new DataColumn("StudentID",Type.GetType("System.String")),
                new DataColumn("ScoreID",Type.GetType("System.String"))
            });
            //把学生成绩信息数据表中添加数据
            StuScoreDt.Rows.Add("1", "00001", "003");
            StuScoreDt.Rows.Add("2", "00002", "001");
            StuScoreDt.Rows.Add("3", "00003", "002");
            StuScoreDt.Rows.Add("4", "00004", "001");
            StuScoreDt.Rows.Add("5", "00005", "004");

            return ds;
        }

添加一个数据查询方法

static void QueryStuScoresByID(string StudentID)
        {
            //获取数据集
            DataSet ds = BuildDataSet();
            //获取数据表
            DataTable dtStu = ds.Tables["Student"];
            DataTable dtScore = ds.Tables["Score"];
            DataTable dtStuScore = ds.Tables["StudentScore"];

            var query1 =
                from stu in dtStu.AsEnumerable()
                from score in dtScore.AsEnumerable()
                from stuscore in dtStuScore.AsEnumerable()
                where stu.Field<string>("StudentID").Equals(stuscore.Field<string>("StudentID"))
                where score.Field<string>("ScoreID").Equals(stuscore.Field<string>("ScoreID"))
                where stu.Field<string>("StudentID").Equals(StudentID)
                //使用匿名类
                select new
                {
                    Name = stu.Field<string>("StudentName"),
                    Math_score = score.Field<double>("Math"),
                    Chinese_score = score.Field<double>("chinese"),
                    English_score = score.Field<double>("English")
                };
            Console.WriteLine("查询ID为:{0}的学生成绩如下:", StudentID);
            foreach (var item in query1)
            {
                Console.WriteLine("姓名:{0},数学:{1},语文:{2},英语:{3}",
                    item.Name,item.Math_score,item.Chinese_score,item.English_score);
            }
        }

在Main方法中添加如下代码进行测试:

//创建DataSet
BuildDataSet();
//计算查询效率
Stopwatch sw = new Stopwatch();
sw.Start();
//执行查询
QueryStuScoresByID("00001");
sw.Stop();
Console.WriteLine("执行耗时:{0}毫秒",sw.ElapsedMilliseconds.ToString());
Console.ReadKey();

编译运行结果如下:
运行结果

  • 使用查询创建查询数据表
    LINQ to DataSet通过DataTableExtensions类提供的扩展方法CopyToDataTable(),会把数据表中获取到的查询结果直接复制到一个新的数据表(DataTable)中,从而可以把查询结果绑定到界面控件DataGridView等。
    CopyToDataTable()包含3个重载版本:
    1.public static DataTable CopyToDataTable(IEnumerable source) where T : DataRow
    2.public static void CopyToDataTable(IEnumerable source,DataTable table,LoadOption options) where T : DataRow
    3.public static void CopyToDataTable(IEnumerable source,DataTable table,LoadOption options,FillErrorEventHandler errorHandler) where T : DataRow
    table:目标数据表对象,用来保存数据
    options:指定DataTable的加载属性
    errorHandler:一个函数委托,可以指定自定义的异常处理操作
    CopToDataTable()执行过程
    1.复制源表中DataTable(实现IQueryable接口的DataTable对象)。IEnumerable源通常来源于LINQ to DataSet表达式或方法查询
    2.目标DataTable的架构从源表中第一个DataRow对象的列生成,克隆表的名称是源表名称加上单词query
    3.对于源表中的每一行,把行内容复制到新DataRow对象中,然后把这个对象插入到目标DataTable中
    4.复制完源表中所有DataRow对象后,返回复制的DataTable。如果源序列不包含任何DataRow对象,则返回一个空的DataTable

在程序中添加如下方进行数据拷贝:

static void UseCopyToDt()
        {
            //获取数据集
            DataSet ds = BuildDataSet();
            //获取数据表
            DataTable dtStu = ds.Tables["Student"];
            DataTable dtScore = ds.Tables["Score"];
            DataTable dtStuScore = ds.Tables["StudentScore"];
            var query1 =
                from stu in dtStu.AsEnumerable()
                from score in dtScore.AsEnumerable()
                from stuscore in dtStuScore.AsEnumerable()
                where stu.Field<string>("StudentID").Equals(stuscore.Field<string>("StudentID"))
                where score.Field<string>("ScoreID").Equals(stuscore.Field<string>("ScoreID"))
                where (int)stu["StudentAge"] > 20
                select stu;

            DataTable newDt = query1.CopyToDataTable();
            Console.WriteLine("学生列表:");
            foreach(var item in newDt.AsEnumerable())
            {
                Console.WriteLine("ID:{0},姓名:{1},性别:{2},年龄:{3}",
                    item["StudentID"],item["StudentName"],item["StudentSex"],item["StudentAge"]);
            }
        }

在Main方法中添加如下测试代码:

Console.WriteLine();

            sw.Start();
            //执行拷贝
            UseCopyToDt();
            sw.Stop();
            Console.WriteLine("拷贝执行耗时:{0}毫秒", sw.ElapsedMilliseconds.ToString());

编译运行结果如下:
运行结果
在实际应用中,使用CopyToDataTable()创建副本通常用于界面绑定

  • 修改表中字段数据
    在LINQ to DataSet中使用Field()方法来获取数据表中指定字段数据,也可以使用SetField()来对字段数据进行修改
    DataRowExtensions.SetField()方法的3个重载版本
    1.public static void SetField(DataRow row,DataColumn column,T value);
    2.public static void SetField(DataRow row,int columnIndex,T value);
    3.public static void SetField(DataRow row,string columnName,T value);
    column:表示要设置数据的列对象(DataColumn类型)
    columnIndex:从0开始的要设置数据的列索引
    columnName:要设置数据的列名称
    通常来说一个数据表的列名是固定的,所以建议使用列名指定数据的列

在程序中添加一个修改指定学生年龄的方法:

//修改学生的年龄
        static void AddStudentAge(string studentID, int age)
        {
            //获取数据集
            DataSet ds = BuildDataSet();
            //获取得学生数据表
            DataTable dtStu = ds.Tables["Student"];
            var query2 =
                from stu in dtStu.AsEnumerable()
                where stu.Field<string>("StudentID").Equals(studentID)
                select stu;
            
            foreach (var item in query2)
            {
                Console.Write("学号为:{0}的学生,{1},原始年龄为:{2}\n",
                    item["StudentID"],item["StudentName"],item["StudentAge"]);
                item.SetField<int>("StudentAge", age);
                Console.Write("学号为:{0}的学生,{1},修改后年龄为:{2}\n",
                    item["StudentID"], item["StudentName"], item["StudentAge"]);
            }
        }

在Main方法中添加如下代码进行测试:

 Console.WriteLine();
            sw.Start();
            //执行拷贝
            AddStudentAge("00001", 30);
            sw.Stop();
            Console.WriteLine("修改记录执行耗时:{0}毫秒", sw.ElapsedMilliseconds.ToString());

编译运行结果如下:
运行结果
注意:SetField()方法是直接修改数据表中的记录。如果要保持原数据表不变,那么在使用SetField()之前,应该先备份源数据表(使用CopyToDataTable()方法进行备份)。

  • 数据视图DataView
    数据视图DataView,是常用的只读形式数据保存形式,可以把它绑定到UI界面,以用户提供形象动态的数据查阅功能。
    DataView本身可以从DataTable或DataSet获取,也可以通过LINQ查询来获取DataView。
    在LINQ to DataSet中,可以使用DataTableExtensions.AsDataView()扩展方法从DataTable或LINQ查询中创建一个与数据源对应的DataView对象。
    AsDataView()方法包含两个重载版本:
    1.public static DataView AsDataView(DataTable table);
    2.public static DataView AsDataView(EnumerableRowCollection source) where T:DataRow

在程序中添加一个方法,使用LINQ to DataSet查询后转为DataView

//创建DataView
        static void CreateDataView()
        {
            //获取数据集ds
            DataSet ds = BuildDataSet();
            //获取数据表dt
            DataTable dt = ds.Tables["Student"];
            //使用DataTable的AsDataView方法创建DataView
            DataView dv = dt.AsDataView();
            //使用LINQ查询来创建DataView
            EnumerableRowCollection<DataRow> query1 =
                from stu in dt.AsEnumerable()
                select stu;
            //根据LINQ查询获取到的结果来创建DataView
            DataView dv_stu = query1.AsDataView();
            Console.WriteLine("DataView数据输出:");
            Console.WriteLine("所有学生:");
            Console.WriteLine("ID\t姓名\t性别\t年龄");
            foreach (DataRowView drv in dv)
            {
                for (int i = 0; i < drv.Row.ItemArray.Length; i++)
                {
                    Console.Write(drv[i]+"\t");
                }
                Console.WriteLine();
            }
            Console.WriteLine();
            EnumerableRowCollection<DataRow> query2 =
                from stu in dt.AsEnumerable()
                where stu.Field<String>("StudentName").StartsWith("杨")
                select stu;
            DataView dv_filter = query2.AsDataView();

            Console.WriteLine("姓杨的学生:");
            Console.WriteLine("ID\t姓名\t性别\t年龄");
            foreach (DataRowView drv in dv_filter)
            {
                for (int i = 0; i < drv.Row.ItemArray.Length; i++)
                {
                    Console.Write(drv[i]+"\t");
                }
                Console.WriteLine();
            }
            Console.WriteLine();
            EnumerableRowCollection<DataRow> query3 =
                from stu in dt.AsEnumerable()
                orderby stu.Field<int>("StudentAge")
                select stu;
            DataView dv_sort = query3.AsDataView();
            Console.WriteLine("按学生的年龄进行从小到大的排序:");
            Console.WriteLine("ID\t姓名\t性别\t年龄");
            foreach (DataRowView drv in dv_sort)
            {
                for (int i = 0; i < drv.Row.ItemArray.Length; i++)
                {
                    Console.Write(drv[i] + "\t");
                }
                Console.WriteLine();
            }
        }

添加另一个方法直接使用DataTable转为DataView,并且直接做相关查询、排序的过滤

static void UseDataView()
        {
            //获取数据集ds
            DataSet ds = BuildDataSet();
            //获取数据表dt
            DataTable dt = ds.Tables["Student"];
            //根据Datatable的AsDataView方法获取到DataView
            DataView dv = dt.AsDataView();
            //设置DataView的过滤信息使用RowFilter
            dv.RowFilter = "StudentAge > 20";
            Console.WriteLine("年龄大于20岁的学生信息:");
            Console.WriteLine("ID\t姓名\t性别\t年龄");
            
            foreach (DataRowView drv in dv)
            {
                for (int i = 0; i < drv.Row.ItemArray.Length; i++)
                {
                    Console.Write(drv[i] + "\t");
                }
                Console.WriteLine();
            }
            Console.WriteLine();
            //清除查询条件
            dv.RowFilter = string.Empty;//这里也可以写为dv.RowFilter = null;
            dv.RowFilter = "StudentName like '杨%'";
            Console.WriteLine("姓杨的学生信息:");
            Console.WriteLine("ID\t姓名\t性别\t年龄");

            foreach (DataRowView drv in dv)
            {
                for (int i = 0; i < drv.Row.ItemArray.Length; i++)
                {
                    Console.Write(drv[i] + "\t");
                }
                Console.WriteLine();
            }
            Console.WriteLine();

            //清除查询条件
            dv.RowFilter = string.Empty;//这里也可以写为dv.RowFilter = null;

            dv.Sort = "StudentAge asc,StudentName desc";
            Console.WriteLine("按学生年龄升序,姓名降序排列:");
            Console.WriteLine("ID\t姓名\t性别\t年龄");

            foreach (DataRowView drv in dv)
            {
                for (int i = 0; i < drv.Row.ItemArray.Length; i++)
                {
                    Console.Write(drv[i] + "\t");
                }
                Console.WriteLine();
            }
            Console.WriteLine();
            //清除查询条件
            dv.RowFilter = string.Empty;//这里也可以写为dv.RowFilter = null;
        }

在Main方法中添加如下代码进行测试:

Console.WriteLine();
            sw.Start();
            //使用DataViews查询数据
            CreateDataView();
            sw.Stop();
            Console.WriteLine("查询记录执行耗时:{0}毫秒", sw.ElapsedMilliseconds.ToString());

            Console.WriteLine();
            sw.Start();
            //使用DataViews查询数据
            UseDataView();
            sw.Stop();
            Console.WriteLine("查询记录执行耗时:{0}毫秒", sw.ElapsedMilliseconds.ToString());

编译运行的结果如下:
运行结果
注意:直接使用DataView可以进行查询过滤和排序,但只是它的排序和过滤功能有限,无法实现自定义的过滤函数和排序方法,在进行复杂的过滤或排序操作时,可以先使用LINQ查询来创建一个DataView,作为一个最终或者是一个临时的视图,然后再在这个视图上进行简单的查询过滤或排序。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值