惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

阮一峰的网络日志
阮一峰的网络日志
D
Darknet – Hacking Tools, Hacker News & Cyber Security
S
Schneier on Security
The Last Watchdog
The Last Watchdog
Cyberwarzone
Cyberwarzone
S
Securelist
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
C
Cyber Attacks, Cyber Crime and Cyber Security
L
Lohrmann on Cybersecurity
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
博客园 - 司徒正美
The Cloudflare Blog
V
V2EX
博客园_首页
博客园 - 聂微东
Vercel News
Vercel News
人人都是产品经理
人人都是产品经理
G
GRAHAM CLULEY
T
Tenable Blog
Last Week in AI
Last Week in AI
Y
Y Combinator Blog
L
LINUX DO - 最新话题
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
SecWiki News
SecWiki News
博客园 - 三生石上(FineUI控件)
S
Secure Thoughts
N
News | PayPal Newsroom
T
The Blog of Author Tim Ferriss
The GitHub Blog
The GitHub Blog
T
Troy Hunt's Blog
博客园 - 【当耐特】
Forbes - Security
Forbes - Security
H
Hacker News: Front Page
A
About on SuperTechFans
B
Blog RSS Feed
Engineering at Meta
Engineering at Meta
MongoDB | Blog
MongoDB | Blog
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
罗磊的独立博客
D
DataBreaches.Net
P
Privacy & Cybersecurity Law Blog
Schneier on Security
Schneier on Security
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Google DeepMind News
Google DeepMind News
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Jina AI
Jina AI
D
Docker
P
Proofpoint News Feed

博客园 - greater

Matlab 7.0不断重启问题解决方法 安装Matlab过程中遇到拒绝访问怎么办? NUnit图解(一) [翻译]Pro C# 2008 and the .NET 3.5 Platform, Fourth Edition 第二十四章 LINQ API编程(三) [翻译]Pro C# 2008 and the .NET 3.5 Platform, Fourth Edition 第二十四章 LINQ API编程(一) 迷人舞步 难译的英文单词 Linq 之Expression Tree再思考 VS2008代码段快捷方式小记 Linq To SQL分页失败后引发的思考 Linq之查询非泛型集合 函数式编程的浅议 Linq操作符之筛选特定位置的元素 Linq与斐波那契数列共舞 Linq的那些事——从Linq扩展方法回顾C#语言基础 Linq To Object实例之过滤字符集 Linq之C#3.0语言扩展 Linq to DataSet 之Access查询 从101 LINQ Samples开始
[翻译]Pro C# 2008 and the .NET 3.5 Platform, Fourth Edition 第二十四章 LINQ API编程(二)
greater · 2008-09-03 · via 博客园 - greater

本章翻译目的为学习之用,英文版权属原作者所有,中文版权根据turingbook的贴子归图灵,如有侵权,请告知删除,禁止用于商业用途!在此特别鸣谢图灵的傅老师(本章翻译的贴出征得她的同意)和杨福川(为大家介绍了这本好书)。本人翻译水平有限,错误之处难免望大家批评指正!本文仅摘出一部分。

获取与LINQ兼容的DataTable

为了说明DataSet扩展的使用,假设你已经创建了一个LinqOverDataSet的C#控制台程序。注意,在你创建.NET 3.5项目的时候,就会自动添加System.Core.dll和System.Data.DataSetExtensions.dll的引用;但是,对于这个例子,添加额外的引用,这些引用在第23章中创建的AutoLotDAL.dll程序集中,并且用以下的逻辑更新初始代码文件:

using System.Data;

using AutoLotDisconnectedLayer;

namespace LinqOverDataSet

{

    class Program

    {

        static void Main(string[] args)

        {

            Console.WriteLine("***** LINQ over DataSet *****"n");

            // 获取包含the AutoLot 数据库中当前存货清单 DataTable 的数据.

            InventoryDALDisLayer dal = new InventoryDALDisLayer(

            @"Data Source=(local)"SQLEXPRESS;Initial Catalog=AutoLot;" +

            "Integrated Security=True");

            DataTable data = dal.GetAllInventory();

            // 像如下调用方法

            Console.ReadLine();

        }

    }

}

       当你希望转换ADO.NET DataTable成LINQ兼容的对象的时候,你只需要简单的调用由DataTableExtensions类定义的AsEnumerable()扩展方法。它会返回一个EnumerableRowCollection对象,该对象包含了DataRows集合。运用EnumerableRowCollection类,接下来你就能如期地操作每一行。举一个简单的例子:

    static void PrintAllCarIDs(DataTable data)

    {

        // 获取DataTable的可枚举版本.

        EnumerableRowCollection enumData = data.AsEnumerable();

        // 打印 the car ID 的值.

        foreach (DataRow r in enumData)

            Console.WriteLine("Car ID = {0}", r["CarID"]);

    }

因为EnumerableRowCollection实现了IEnumerable<T>接口,它被允许用以下的代码段捕获返回值:

    // 存储IEnumerable<T>类型的返回值

    IEnumerable<DataRow> enumData = data.AsEnumerable();

    // 隐藏存储的返回值.

    var enumData = data.AsEnumerable();

在这里,实际上我们没有运用LINQ查询;然而,关键是enumData对象现在能够成为LINQ查询表达式的对象。我们也注意到EnumerableRowCollection确实包含了DataRow对象集合,当我们使用类索引器而非每一个子类打印出CarID列的值。

       在大多数情况下,你不需要声明一个EnumerableRowCollection类型变量来存储AsEnumerable()的返回值。甚至,可以在查询表达式中调用该方法。有一个更有趣的方法,它获取CarID的映射,在CarID大于5之处返回所有DataTable的实例。

    static void ApplyLinqQuery(DataTable data)

    {

        // Project a new result set containing

        // the ID/color for rows with a CarID > 5

        var cars = from car in data.AsEnumerable()

                   where

                   (int)car["CarID"] > 5

                   select new

                   {

                       ID = (int)car["CarID"],

                       Color = (string)car["Color"]

                   };

        Console.WriteLine("Cars with ID greater than 5:");

        foreach (var item in cars)

        {

            Console.WriteLine("-> CarID = {0} is {1}", item.ID, item.Color);

        }

    }

DataRowExtensions.Field<T>()扩展方法的作用

当前LINQ查询表达式的不友好的一个方面是,我们在使用许多类型转换操作和运用DataRow索引器来获得结果集,如果我们尝试转换不兼容的数据类型,这就会产生运行时异常。为了植入一些强类型到我们的查询当中,我们可以使用DataRow类型的Field<T>()扩展方法。这样做是为了提高查询的类型安全性,同时在编译的时候检查数据类型的兼容性。

考虑以下的更新:

    var cars = from car in data.AsEnumerable()

               where

               car.Field<int>("CarID") > 5

               select new

               {

                   ID = car.Field<int>("CarID"),

                   Color = car.Field<string>("Color")

               };

注意这种情况下我们可以调用Field<T>()和定义一个类型参数来表示底层列的数据类型。用列名作为参数并传递给该方法。进行额外的编译检查时,在考虑EnumerableRowCollection作用的时候,最实用的就是使用Field<T>(),而非DataRow索引器。

       除此以外我们调用AsEnumerable()方法,大体上LINQ查询格式和你在第十四章看到的完全相同。基于这一点,我不厌其烦的在这里重复很多LINQ操作符细节。如果你希望看更多的例子,在.NET Framework 3.5开发文档中可以搜索到关于“LINQ to DataSet示例“的主题。

从LINQ查询合成新DataTable

在基于LINQ查询结果集并且不使用映射,简单地把数据移植到新DataTable是可行的。当你有一可用于表示为IEnumerable<T>底层类型的结果集的时候,你可以调用结果集中的CopyToDataTable<T>()扩展方法。比如:

    static void BuildDataTableFromQuery(DataTable data)

    {

        var cars = from car in data.AsEnumerable()

                   where

                   car.Field<int>("CarID") > 5

                   select car;

        // 用这一结果集创建一个新的DataTable.

        DataTable newTable = cars.CopyToDataTable();

        // 打印 DataTable.

        for (int curRow = 0; curRow < newTable.Rows.Count; curRow++)

        {

            for (int curCol = 0; curCol < newTable.Columns.Count; curCol++)

            {

                Console.Write(newTable.Rows[curRow][curCol].ToString().Trim() + ""t");

            }

            Console.WriteLine();

        }

    }

注意:通过AsDataView<T>()方法把LINQ查询转换为DataView类型是可行的。

这种方法在用LINQ查询的结果作为数据绑定源的时候非常有效。例如,WinForms的DataGridView(ASP.NET下是GridView)都支持一个叫DataSource的属性。你可以把LINQ结果集绑定到grid控件去,如下所示:

// 假设 myDataGrid 是基于用户控件的grid对象.

myDataGrid.DataSource = (from car in data.AsEnumerable()

where

car.Field<int>("CarID") > 5

select car).CopyToDataTable();

既然你已经了解LINQ to DataSet的作用,让我们把注意转向LINQ to SQL。

源代码:LinqOverDataSet示例在第二十四章的子目录下。