Chapter10 Querying with LINQ

.NET3.5引进了一个新的技术叫做LINQ。从那时候开始,LINQ逐渐成为.NET开发的一个集成技术。在.NET4.0和4.5,微软都更新了LINQ进一步加强它的性能。LINQ的设计初衷是消除.NET语言和查询语言之间的代沟。.NET语言提供了强类型和面向对象的开发,查询语言例如SQL,其语法专门用来作为查询操作。随着LINQ在.NET框架中的引入,查询在.NET中成为了first-class的概念,无论你谈论的是对象,XML,或者数据库查询。
尽管LINQ具有扩展性,能够应用到其余的数据源,LINQ包含了三种基本查询类型,LINQ to Objects,LINQ to XML,还有一种是在数据库环境下的使用,例如LINQ to SQL或者LINQ to Entities。每一种查询类型提供了具体的功能,专门为不同数据来源设计打造。
这一章对上述查询类型一一介绍。这一章同样涵盖了.NET CLR的语言特色,使用它来创建LINQ查询,还有VS中提供的支持LINQ的工具。

注意 尽管这章主要聚焦于LINQ在.NET框架中的能力,LINQ其实是高度可扩展的,可以用来创造对任何数据源的查询框架。如何实现你自己的LINQ provider不在本书的介绍范围内。

LINQ TO OBJECTS

LINQ的第一个和基本风味就是LINQ to Objects。LINQ to Objects允许你对任何可
枚举的对象(只要该对象实现了IEnumerable接口)进行复杂的查询操作。虽然在.NET中生成可查询和排序的可枚举对象并不是新的概念,在.NET3.5之前的版本中,这通常意味着你需要写大量的代码。通常,那些代码都会非常复杂,变得难以让其它开发者理解和阅读,变得难以维护。

Understanding Traditional Query Methods

为了理解LINQ是怎么样提高你查询集合的能力的,来看看如果没有LINQ,你如何完成查询。

Replacing Traditional Queries with LINQ

LINQ生来就是为了解决传统的查询对象集合方法的弊端。LINQ并不需要详详细细地指明你的查询是如何执行的,它使你能够站在一个更抽象的层面。通过定义你的查询返回什么,你将其余的都留给了.NET和它的编译器来决定这个查询到底如何进行。
在之前的部分,你看到了没有LINQ的帮助如何查询对象集合,在这一部分,你会看到LINQ如何化繁为简。
在你开始之前,理解LINQ是.NET框架的一个扩展。基本LINQ功能存在于System.Core.dll里。这个assembly没有取代任何存在的.NET框架功能,而是对其功能进行了扩展。另外,默认情况下,VS中的工程包扩了对这个assembly的引用,所以当开始一个新的AN网页工程时,LINQ已经在向你招手了。

Basic LINQ Queries and Projections

如果你记得的话,前面的sample产生了movies列表,然后将这个列表绑定到GridView控件中。下面的代码展示了如何修改让LINQ完成查询将结果绑定到GridView中。

protected void Page_Load(object sender, EventArgs e)
{
var movies = GetMovies();
var query = from m in movies
select m;
this.GridView1.DataSource = query;
this.GridView1.DataBind();
}

如果你拆析这段代码,你可以发现三个动作。首先,使用GetMovies方法获取这个集合。然后,这段代码使用了简单的LINQ查询选择了movies集合中的所有Movie对象。注意这个具体的LINQ查询在查询语句中使用了from和select关键字。这些语法是.NET语言中的first-class成员。所以VS能提供给你开发的帮助,例如强类型校验和IntelliSense,这使得你在代码中更容易发现和解决问题。
这个查询定义了一个新的变量m。这个变量在这个查询中有两个用处,第一,通过在from语句中定义m,你指示了LINQ使用这个变量m来代表集合中每个item,在这个例子中就是Movie对象。告诉LINQ这个能够让它理解你所查询对象的结构,你会看到,这同样帮助你生成这个查询。
m在查询中的第二个作用是在select语句中。在select语句中使用m告诉LINQ输出一个投影,对应m的结构。投影指的是将独享转换为另一种新的形式的操作,新的形式只包括你需要的特征。在这个例子中,这意味着LINQ生成一个投影,匹配Movie的结构。
通过指明你从查询中想要返回的字段可以很简单地 生成你自己的投影。例如下面所示

protected void Page_Load(object sender, EventArgs e)
{
var movies = GetMovies();
var query = from m in movies
select new { m.Title, m.Genre };
this.GridView1.DataSource = query;
this.GridView1.DataBind();
}

注意你定义了一个新的投影,只包含Title和Genre的值,而不是选择m。
你可以进一步地定义字段名字。例如,你可能想要更加明显地给Title和Genre字段命名来描述它们的内容。使用LINQ,命名任务和简单。如下面所示

protected void Page_Load(object sender, EventArgs e)
{
var movies = GetMovies();
var query = from m in movies
select new { MovieTitle = m.Title, MovieGenre = m. Genre };
this.GridView1.DataSource = query;
this.GridView1.DataBind();
}

这个例子显示的定义了结果集合的字段为MovieTitle和MovieGenre。最后,代码将GridView绑定到LINQ查询返回的可枚举列表。
LINQ也允许你对结果进行排序,用的是order by语句。

protected void Page_Load(object sender, EventArgs e)
{
var movies = GetMovies();
var query = from m in movies
orderby m.Title descending
select new { MovieTitle = m.Title, MovieGenre = m. Genre };
this.GridView1.DataSource = query;
this.GridView1.DataBind();}

LINQ语法另一个很棒的特色是对代码可读性和可理解性的显著提升。LINQ允许你表达你的查询的意图,指示编译器你想要你的代码做什么,但是将如何完成留给了编译器。

Ordering Results Using a Custom Comparer

有时候你需要更多的控制在结果比较上,而不是默认比较器所提供的。在这些情况下,你可以制造定制的比较器,然后使用OrderBy或者OrderByDescending重载传递给order by操作。为了生成定制的比较器,你可以生成从IComparer<>继承的类。给定上面的例子,如果你用director排序,结果会由director的firstname决定,因为字符串是有firstname紧跟着lastname构成的。如果你想要结果是由lastname决定的,你需要生成一个自定制的比较器。

using System.Collections.Generic;
public class LastNameComparer : IComparer<string>
{
public int Compare(string x, string y)
{
var director1LastName = x.Substring(x.LastIndexOf(' '));
var director2LastName = y.Substring(y.LastIndexOf(' '));
return director1LastName.CompareTo(director2LastName);
}
}

Deferred Execution

LINQ的一个有趣的特色就是它的延迟执行。这意味着即使你可能在你代码的某一处执行了查询语句,LINQ足够聪明延迟查询的实际操作直到真实需要,举个例子,在前面的例子中,尽管LINQ的查询在绑定GridView控件之前,LINQ直到GridView开始枚举查询结果时才会执行你所定义的查询。
延迟执行的一个最大好处就是在执行LINQ之前修改它的能力,尽管LINQ查询返回一个IQueryable,这继承于IEnumerable,知道你遍历它,数据才能用。尝试迭代结果才会造成LINQ执行查询。还有一些方法也会造成LINQ查询立即执行,例如以To开头的方法,例如ToList()方法,还有Count()方法。
因为查询的执行只发生在你迭代结果的时候。你可以添加其余的过滤器到查询中。

Filtering Data Using LINQ

LINQ也支持使用类似SQL where的语法添加查询过滤。

protected void Page_Load(object sender, EventArgs e)
{
var movies = GetMovies();
var query = from m in movies
where m.Genre==0
select m;
this.GridView1.DataSource = query;
this.GridView1.DataBind();
}

通过在LINQ查询中添加简单的where从句,查询返回的记过过滤到只显示genre为0的movie。
注意,因为LINQ是.NET的first-class成员,VS在你构造LINQ查询时能够提供优秀的编码体验。

Grouping Data Using LINQ

LINQ也大大方便了数据分组,使用SQL类似的group语法。看看下面的例子

protected void Page_Load(object sender, EventArgs e)
{
var movies = GetMovies();
var query = from m in movies
where m.Genre==0
select m;
this.GridView1.DataSource = query;
this.GridView1.DataBind();
}

这个LINQ查询使用了group关键字,将movie数据根据genre分组。两位,因为一个group动作不会自动的产生任何输出,这个查询生成了一个自定制的查询投影。
使用LINQ来做分组减少了你需要写的代码。

Using Other LINQ Operators

除了基本的选择,过滤和分组,LINQ也包括了很多执行在集合的操作,大多数这些操作你能够用在任何集合中,这些操作和SQL中的Count,Min,Max,Average还有Sum很像。

protected void Page_Load(object sender, EventArgs e)
{
var movies = GetMovies();
this.TotalMovies.Text = movies.Count.ToString();
this.LongestRuntime.Text = movies.Max(m => m.RunTime).ToString();
this.ShortestRuntime.Text = movies.Min(m => m.RunTime).ToString();
this.AverageRuntime.Text = movies.Average(m => m.RunTime).ToString();}

这个列表演示了Count,Max,Min和Averate操作符在movies集合的使用。注意除了Count操作符,你必须提供操作的字段。你使用Lambda表达式完成这个。

Making LINQ Joins

LINQ也支持将来自不同集合的数据粘合起来,使用熟悉的SQL join语法。例如,在目前的例子中,你显示genre为数字ID。将每个genre的名字显示出来应该更为可取。为了满足这个,你要生成一个Genre类。

Paging Using LINQ

LINQ使得你的应用中的分页逻辑更加简单,使用Skip和Take方法。Skip方法使你能够省略结果集合中指定数量的纪录。Take方法使你能够指定结果集合返回的纪录数量。通过调用Skip和Take,你可以从结果集合中返回指定位置指定数量的纪录。

LINQ TO XML

LINQ的第二道风味叫做LINQ to XML。正如名字所暗示的,LINQ to XML允许你使用相同的LINQ语法查询XML文档。和基本的LINQ特色一样,.NET中的LINQ to XML特色是做为基本.NET框架的延生包括在内的,也不会改变现在的功能。同时,和core LINQ特色一样,LINQ to XML特色包含在它们自己的assembly中,System.Xml.Linq。
这一部分向你展示如何使用LINQ来查询XML,使用这个基本的movie数据,但是将其转换为XML。
所你可以看到如何使用LINQ to XML来查询XML文档。

A Simple LINQ to XML Example

var query = from m in
XElement.Load(MapPath("Movies.xml")).Elements("Movie")
select m;
this.GridView1.DataSource = query;
this.GridView1.DataBind();

注意在这个query中,你告诉LINQ去哪里加载XML数据,并且从XML文档中的什么elements中获取数据,在这里就是所有的Movie元素。除了一点点的差别,LINQ查询和之前的是一样的。
注意这个查询的结果集合中的字段并不像你期望的那样返回节点信息,并且每个子节点作为GridView的一个个别字段。这是因为查询返回的是XElement对象集合,并不是你期待的Movie对象集合。这是因为仅仅凭LINQ自己,没有办法知道每个节点应该映射为什么对象。谢天谢地,你可以在查询中增加一点映射逻辑来告诉它每个节点映射为Movie对象,并且每个节点的子元素应该映射为每个Movie对象的特征。

protected void Page_Load(object sender, EventArgs e)
{
var query = from m in XElement.Load(MapPath("Movies.xml")).Elements("Movie")
select new Movie {
Title = (string)m.Element("Title"),
Director = (string)m.Element("Director"),
Genre = (int)m.Element("Genre"),
ReleaseDate = (DateTime)m.Element("ReleaseDate"),
RunTime = (int)m.Element("RunTime")
};
this.GridView1.DataSource = query;
this.GridView1.DataBind();
}

正如你看到的,这个查询现在包含了映射逻辑,这样LINQ知道你的意图是什么,即结果集合包含了Movie元素的内部节点的值。

警告 注意XElement的Load方法试图加载整个XML文档。所以,如果XML文档很大,使用这个方法加载可能不太明智。

Join XML Data

LINQ to XML支持所有LINQ to Objects拥有的过滤和分组操作。它也支持数据联合,可以从两个不同的XML文档中联合数据,这个任务之前是非常困难的。

LINQ TO SQL

LINQ to SQL,正如名字暗示的,允许你能快速并且方便的查询基于SQL的数据源,例如SS2005以上。和之前LINQ的风味一样,LINQ to SQL是核心.NET框架的扩展。它的特色位于System.Data.Linq assembly。

Using the O/R Mapper

除了通常的IntelliSense和强类型校验,LINQ to SQL还包括了一个基本的O/R映射。这个O/R映射是你能快速的将基于SQL的数据源映射为CLR对象。
你通过增加LINQ to SQL类对象到你的工程来使用O/R映射器。LTS文件类型允许你轻松的并且快速生成便于LINQ查询访问的数据环境。
当你将这个文件加入你的工程时,VS会通知你它想要将这个LTS文件放到你的App_Code目录。因为把这个LINQ to SQL文件放到那个目录下,你在你网站工程的任意地方都能访问到。
这个文件被创建后,VS自动的打开了这个文件。这个简单的O/R映射设计工具允许你增加,生成,移动和相关数据对戏那个。当你修改对象时,LINT to SQL生成对象类,返照每个对象的结构。稍后,当你准备好开始对这些数据对象写LINQ查询时,这些类允许VS提供你IntelliSense帮助,强类型和编译时的类型校验。因为这个O/R映射器主要是用来让LINQ to SQL使用的,生成SQL对象的CLR对象,例如tables,views。
当设计板块打开后,打开VS Server Explorer tool,定位到Movies数据库,扩展数据库的Tables文件夹,将Movies表拉出来。注意当你将这个数据库表拉出到设计板块上时,它自动的被询问来识别它的结构。一个对应的实体类由设计器生成,并且显示在设计板块上。
当你将table对象拉到LTS设计板块上时,VS检查table的名字,如果需要的话,自动的单数话这个类名字。它这么做是为了帮助你更好地遵循.NET框架的类命名标准。例如,如果你将一个称为Products的表从数据拉到设计面板上,它会自动的选择单数的名字Product作为类的名字。
不幸的是,虽然这个设计器一般对类的命名很擅长,但是它不是百分百准确的。在这里就是,看看它是怎么把Movies表单数化为Movy的。谢天谢地,这个设计器允许你改变实体的名字。
当你添加了Movie实体后,将Genres表也拉到设计板块上来。再一次,VS生成了这个表的类表达(注意它给了这个表一个单数化的名字Genre)。另外,它检测到了Movie和Genre中间的一个foreign key关系。因为它检测到了这个关系,它在两个表之间增加了一条虚线。线的箭头表示了foreign key的方向。

Accessing and Querying Data

因为你现在建立了你的LTS文件,访问和查询数据变得很简单

Accessing Data

你在web form中生成一个数据环境,你可以在这个数据环境中访问数据。

<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
MoviesDataContext dc = new MoviesDataContext();
}
</script>

在这个例子中,你生成了一个MoviesDataContext实例,这是你增加的LTS文件生成的数据环境类的名字。

注意 因为这个数据环境类是自动的由LTS文件产生的,当你生成一个新的LTS文件后,它会自动的改变。这个类的名字是有你的LTS类文件后加上DataContext后缀构成的。

Writing LINQ Queries

当你添加了你的数据环境后,你可以开始对其构造LINQ查询。正如前面提到的,因为LINQ to SQL-生成的对象类反映了数据库表的结构,你可以得到IntelliSense的支持。

    protected void Page_Load(object sender, EventArgs e)
    {
        MoviesDataContext dc = new MoviesDataContext();
        var query = from m in dc.Movies
                    select m;
        GridView1.DataSource = query;
        GridView1.DataBind();
    }

注意你不需要写任何的数据库访问代码。LINQ已经为你做好了这一切,甚至基于LINQ语法生成SQL查询。你可以观察LINQ产生的SQL。

  MoviesDataContext dc = new MoviesDataContext();
        var query = from m in dc.Movies
                    select m;
        System.Diagnostics.Debug.WriteLine(query);
        GridView1.DataSource = query;
        GridView1.DataBind();

正如你看到的,这个产生的SQL是标准的SQL语法,LINQ擅长于优化它所生成的查询,甚至是例如分组查询这种复杂的查询。

protected void Page_Load(object sender, EventArgs e)
{
MoviesDataContext dc = new MoviesDataContext();
var query = from m in dc.Movies
group m by m.Genre into g
select new { Genre = g.Key, Count = g.Count() };
System.Diagnostics.Debug.WriteLine(query);
this.GridView1.DataSource = query;
this.GridView1.DataBind();
}

注意LINQ to SQL生成的SQL对你使用的SQL Server的版本进行了优化。

Using Other SQL Query Methods

虽然LINQ to SQL擅长于生成SQl查询,但是会存在使用其他SQL查询方法的场景。

Using a SQL View

使用SQL view,你只需要将SQL view拖拉到LINQ to SQL的设计面板上,就像你对一个标准的SQL table一样。

protected void Page_Load(object sender, EventArgs e)
{
MoviesDataContext dc = new MoviesDataContext();
var query = from m in dc.AllMovies
select m;
System.Diagnostics.Debug.WriteLine(query);
this.GridView1.DataSource = query;
this.GridView1.DataBind();
}

Using Stored Procedures

不想tables和views,这种情况下,LINQ to SQL可以产生特征,stored procedures会需要参数。因为LINQ to SQL的数据环境将其曝露为method,允许你提供方法参数,然后由LINQ翻译为stored procedure参数。
下面展示了一个简单的存储过程,你可以用来获取指定的genre。

CREATE PROCEDURE dbo.GetGenre
(
@id int
)
AS
SELECT * FROM Genre WHERE ID = @id

你可以像添加table或者view一样,添加存储过程到你的LINQ to SQL设计器,通过将它们从Server Explorer拽到LINQ to SQL类设计板块。如果你期望你的存储过程返回数据集合,你应该将存储过程拖拉到返回类型的实体上。上面的存储过程会返回所有匹配ID的Genre纪录,因此,你应该将GetGenres存储过程拖拉到Genres。这告诉这个设计器生成一个返回Genre对象集合的方法。当你将存储过程放到设计版面上,不想tables和views,这个存储过程是出现在设计板块右边的列表上。
当你添加过存储过程后,你可以通过数据环境对它进行访问,正如你访问tables和views一样。正如前面所叙述的一样,LINQ to SQL将其曝露为方法。因此,他们要求你提供提供参数。

Making Insert Update and Delete Queries through LINQ

你不仅可以使用LINQ to SQL来生成强大的查询从数据源选择数据,你同样可以使用LINQ来管理插入,更新和删除操作。LINT to SQL使用SQL结构的对象类代表来生成SQL的插入更新和删除命令。和选择一样,你可以使用存储过程了执行插入更新和删除。

Inserting Data Using LINQ

使用LTS插入数据就是生成一个新的实例,将其添加到这个对象集合中。LINQ类提供了两种方法-InsertOnSubmit和InsertAllOnSubmit-这两个方法使得生成和添加任何对象到LINQ集合变得简单。InsertOnSubmit方法接收一个实体作为方法参数,允许你插入单个实体,而InsertAllOnSubmit方法接收一个集合做诶方法参数,允许你插入一个完全的数据集合。
当你添加你的对象后,LINQ to SQL还要求一步,调用数据环境的SubmitChanges方法。调用这个方法告诉LINQ来启动这个插入过程。下面的例子演示了生成一个Movie对象,将其添加到movies集合中,然后调用SubmitChanges来将变化传递到SQL数据库。

protected void Page_Load(object sender, EventArgs e)
{
MoviesDataContext dc = new MoviesDataContext();
Movie m = new Movie { Title="The Princess Bride",
Director="Rob Reiner", Genre=0,
ReleaseDate=DateTime.Parse("9/25/1987"), Runtime=98 };
dc.Movies.InsertOnSubmit(m);
dc.SubmitChanges();
}

Using Stored Procedures to Insert Data

当然,你可能已经有了复杂的存储过程来处理数据的插入。LINQ使得使用存在的存储过程插入数据变得非常简单。在LINQ to SQL的设计面板上,选择你想要插入数据的实体,在这个例子中就是Movie实体。选择这个实体后,打开它的特征窗口,定位到默认方法部分。
默认方法部分有三个特征,删除,插入和更新-定义了LINQ应该使用的的行为默认的,每个特征都被定义为UseRuntime,这个告诉LINQ在运行时间动态的产生SQL语句。因为你想要使用存储的过程插入数据到table中,打开Insert特征的配置行为对话框。
在这个对话框中,将行为按钮选择从使用运行时间转为自定制,然后选择合适的存储过程。当你选择了这个存储过程后,LINQ自动的将table类匹配到存储过程的输入参数,然而,需要的话,你可以人工的改变。

Updating Data Using LINQ

使用LINQ更新数据和插入数据类似,第一个步是得到你想要更新的具体对象。你可以使用Single方法达到这个目的。这个标量Single方法从集合中返回单个对象。如果多余一条记录匹配这些参数,这个Single方法返回第一个匹配的对象。
当你获得了你想要更新的对戏那个后,你可以改变这个对象的特征值然后调用数据环境的SubmitChanges方法。

protected void Page_Load(object sender, EventArgs e)
{
MoviesDataContext dc = new MoviesDataContext();
var movie = dc.Movies.Single(m => m.Title == "Fletch");
movie.Genre = 1;
dc.SubmitChanges();
}

默认情况下,LINQ to SQL包含了乐观并发。这意味着,如果两个用户从数据库获取了同一条数据,并且试图更新,第一个提交更新的用户获胜。如果第二个用户试图更新这个纪录,LINQ to SQL会检测到这个原来的纪录已经被更新,然后抛出一个ChangeConflictException。

Deleting Data Using LINQ

最后 LINQ to SQL也允许你从你的SQL数据源删除数据。每一个由LINQ to SQL设计器产生的数据类对象同样包含两个方法让你删除对象,DeleteOnSubmit和DeleteAllOnSubmit方法。正如他们的名字暗示的一样,这个DeleteOnSubmit方法从集合中移除一个对象,DeleteAllOnSubmit方法移除集合中所有的纪录。

protected void Page_Load(object sender, EventArgs e)
{
MoviesDataContext dc = new MoviesDataContext();
//Select and remove all Action movies
var query = from m in dc.Movies
where m.Genre == 2
select m;
dc.Movies.DeleteAllOnSubmit(query);
//Select a single movie and remove it
var movie = dc.Movies.Single(m => m.Title == "Fletch");
dc.Movies.DeleteOnSubmit(movie);
dc.SubmitChanges();
}

同其他SQL命令一样,你必须记住调用数据环境的SubmitChanges方法来让这些变化发生在SQL数据源中。

LINQ TO ENTITIES

当你需要快速的构造你的数据接入代码时,LINQ to SQL是一个很棒的工具。如果你的数据设计的非常好,它也能工作的很棒。然而,LINQ to SQL只支持实体类和数据库表的一对一映射。
Entity Framework(EF)是一个对象关系映射器,它允许.NET开发者使用domain-specific对象和关系数据打交道,这个组成了所谓的概念模型。EF也允许连接到许多不同的数据提供者。正因为如此,你可以混合和匹配许多不同的数据库厂商,应用服务器或者协议来设计一个对象聚合,这个对象聚合从不同的表,源,服务构造而成。
LINQ to Entities允许开发者对EF概念模型构造查询。虽然LINQ to SQL查询最终生成了SQL,LINQ to Entities将LINQ查询转换为命令树查询,命令树查询是EF能够理解的,查询是针对EF的,返回的对象既能被EF使用,也能被LINQ使用。虽然背后执行的代码在LINQ to Entities和LINQ to SQL是大为不同的,但是LINQ语法看起来是一样的。

Creating an Entity Framework Data Model

你需要生成一个EF 数据模型来和LINQ to Entities打交道。

Accessing Data

生成一个新的web form来使用data模型显示数据。为了开始使用这个实体数据模型,生成一个EF数据环境。

<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
MoviesEntities dc = new MoviesEntities();
}
</script>

在这个例子中,你生成了一个MoviesEntities的实例,这是LINQ to Entities生成的数据环境类的名字。

Writing LINQ Queries

现在你已经有了一个EF数据环境的实例,你可以开始针对它写LINQ查询。你会注意到针对EF数据模型构造LINQ查询和针对SQL构造LINQ查询看起来一模一样,LINQ to Entities提供了IntelliSense支持。

protected void Page_Load(object sender, EventArgs e)
{
MoviesEntities dc = new MoviesEntities();
var query = from m in dc.EFMovies select m;
GridView1.DataSource = query.ToList();
GridView1.DataBind();
}

SUMMARY

这一章向你介绍了LINQ,这大大的简化了.NET数据的查询。LINQ将查询作为first-class概念,直接嵌入到了.NET框架中。
LINQ的回顾展示了现在执行对象查询的方法,包括基本的数据过滤,分组和排序。你看到了传统的对象查询技术的短板,需要用户不仅定义应该查询什么,还要实际指明查询如何进行。另外,你看到即使是简单的操作也会导致大量复杂的代码,这使得代码的阅读和可维护性都大大变差。
LINQ有三种基本类型,LINQ to Objects,LINQ to XML,LINQ to SQL。LINQ的每一种非为使用基本的查询语法,大大简化了对象,XML和SQL数据源数据查询。你可以使用基本的类SQL语法来选择,过滤和分组。这个查询语法简单明了,易于阅读,而且包含了许多SQL相同的操作符。
LINQ to SQL中包含的O/R映射器使得生成对应SQL结构,类似tables,views和存储过程的CLR对象变得非常简单。当这些CLR对象被生成后,你可以使用LINQ来查询这些对象。
使用LINQ to SQL,你可以通过使用生成的SQL语句或者使用存储的过程,方便地改变数据库中的数据。使用LINQ to Entities,你可以引入使用已经熟悉的LINQ语法将更偏爱的数据库接入技术和EF整合进来。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值