用LINQtoSQL创建Web应用系统(一)

用LINQtoSQL创建Web应用系统(一),第1张

在新的 Net Framework 平台上 Microsoft发布了LINQ(C# VB Net ) 集成语言查询(Language Integrated Query) 也就是通过编程语言来查询数据

数据库 (LINQ to SQL)

DataSet 数据集(LINQ to Dataset)

XML文档 (LINQ to XML)

实体对象 (LINK to Entities)

本文将演示如何在ASP NET 平台上 使用LINQ to SQL构建多层的Web应用程序 在当前的编程领域中 创建N Tier应用程序成为一般的要求 且 NET Framework 提供了灵活的支持 一般而言 N Tier应用程序有如下几个层 表示层 业务逻辑层 数据访问层 数据库层 每一层均完成特定的任务 本篇文章中介绍的架构和经典的N Tier相似 不过数据库层替换新的DataLinq 层 使用LINQ to SQL 完成数据 *** 作        

图 基于LINQ to SQL的N Tier架构

架构思考

如果你有大型ASP NET项目的经历 你可能会注意到更多的时间花在写组件代码 而不是Web页面代码 有时 组件的设计和管理成为一个费时的过程 你可能正遇到架构方面的问题 寻找最好的方式来设计Web应用程序

我写这篇文章的想法是介绍一个好的设计模式 并不是得到一个结论或者声明这是一个最好的N Tier应用程序的设计模式 因为对于架构设计 每一个开发人员总是有自己的观点 所以任何合适的架构阐述都是有争议的 然而 如图 所示 分离不同的代码到不同的层总是一个好的实践 按这样组织代码 可以更方便地维护和扩展应用程序

在图 中 你可以看到业务组件分割到不同的层 组织代码最好的方法是为每一个业务组件创建不同的类库(Class Library) Visual Studio允许在同一个Solution中创建多个项目 因此 我们可以在同一个Solution中加入ASP NET 应用程序和类库Class Library项目 当你在编译Solution时 每一个项目都会生成在bin目录下生成一个assembly程序集文件 方法 我们可以手动复制 DLL文件到应用程序的bin目录 方法 增加项目引用 当你编译Solution时 第二种方法可以自动更新应用程序bin目录的程序集文件 通过这种方式组织代码 可以更容易修改/更新项目的特定代码 也容易从不同的Server上迁移代码 我不想深入探讨架构 这里我通过截屏来解释如何实现

假定你已经具备经典 层架构应用程序的设计经验 我告诉你如何建立层与层之间的引用关系 接着你可以自己建立项目引用 图 上的箭头符号说明了不同层之间的交互 说明如下

( ) 数据访问层引用Data Linq 层( 开源小组注 原文说还需要引用业务外观(Business Facade)层 原文有误)

( ) 业务外观(Business Facade)层引用Data Linq 层和数据访问层 因为业务外观层使用Data Linq层的业务实体来创建表实体(后面进行详细讨论) 同时调用数据访问层的方法

lishixinzhi/Article/program/net/201311/12345

产生此异常,主要是Linq缓存数据和实际数据库数据不一致的情况造成。解决次问题的情况,主要有几种:

1比较简单的方法,不使用Linq提供的SubmitChanges()方式提交更改,而直接执行SQL语句,例如:

dbExecuteCommand("Update [dbo][LinqTest] SET Age=25 Where ID = @p0", 1);

这样虽然比较方便,但是感觉又回到了直接写SQL的时代,毕竟Linq to SQL的目的,就是为了让我们看不见SQL,避免写复杂的SQL语句,而直接 *** 作实体对象,这样也可以避免程序可读性差、不便于维护。所以除非万不得已,还是不太推荐使用此方法。

2参考MSDN的资料,采用Linq提供的解决更新冲突的方法,在异常中捕获冲突,然后手动解决冲突:

try

{

dbSubmitChanges(SystemDataLinqConflictModeContinueOnConflict);

}

catch (SystemDataLinqChangeConflictException ex)

{

foreach (SystemDataLinqObjectChangeConflict occ in dbChangeConflicts)

{

//以下是解决冲突的三种方法,选一种即可

// 使用当前数据库中的值,覆盖Linq缓存中实体对象的值

occResolve(SystemDataLinqRefreshModeOverwriteCurrentValues);

// 使用Linq缓存中实体对象的值,覆盖当前数据库中的值

occResolve(SystemDataLinqRefreshModeKeepCurrentValues);

// 只更新实体对象中改变的字段的值,其他的保留不变

occResolve(SystemDataLinqRefreshModeKeepChanges);

}

// 这个地方要注意,Catch方法中,我们前面只是指明了怎样来解决冲突,这个地方还需要再次提交更新,这样的话,值 //才会提交到数据库。

dbSubmitChanges();

}

1查询生命周期

在进入正题时候,我们先来了解EF Core查询的生命周期。

11LINQ查询会由Entity Framework Core处理并生成给数据库提供程序可处理的表示形式(说白了就是生成给数据库可识别数据形式)。

发送的查询结果(查询表示形式)会被缓存,以便每次执行查询时无需进行11中处理。

12查询结果(查询表示形式)会传递到数据库提供程序

数据库提供程序会识别出查询的哪些部分可以在数据库中求值。

查询的这些部分会转换为特定数据库的查询语言(例如,关系数据库的T-SQL)。

一个或多个查询会发送到数据库并返回结果集(返回的是数据库中的值,而不是实体实例中的)。

13对于结果集中的每一项

131如果这是跟踪查询(后续会讲到),EF会检查数据是否表示已在上下文实例的更改跟踪器中的实体中。

如果是,则会返回现有实体。

如果不是,则会创建新实体、设置更改跟踪并返回该新实体。

132如果这是非跟踪查询(后续会讲到),EF会检查数据是否表示已在此查询的结果集中的实体中。

如果是,则会返回现有实体。非跟踪查询使用弱引用跟踪已返回的实体。如果具有相同标识的上一个结果超出范围,并运行垃圾回收,则可能会获得新的实体实例。

如果不是,则会创建新实体并返回该新实体。

14执行查询时

当调用LINQ运算符时,只会生成查询的内存中表示形式。当我们使用查询结果(查询表示形式)时才会发送到数据库。导致查询发送到数据库的最常见 *** 作如下:

在for循环中循环访问结果:

var blogs = from b in _contextBlog

select new

{

bBlogId,

bUrl

};

//触发数据库查询

foreach(var blog in blogs)

{

var id = blogBlogId;

}

当我们执行完LINQ运算符的时候,从SQL Server Profiler监控里面可以看到,并没有执行的SQL语句,也就是说查询结果blogs并没有立即发送给数据库获取返回数据结果集。

而当我们调试进去for循环时候,SQL Server Profiler监控里面可以看到出现了执行SQL语句。也就是说这时候查询结果blogs才执行发送给数据库返回结果集。

使用ToList、ToArray、Single、Count等运算符

_contextBlogToList();

_contextBlogToArray();

_contextBlogCount();

_contextBlogSingle();

_contextBlogFirst();

执行这种形式运算符也会立即发送到数据库获取结果集的。具体执行过程呈现,这里大伙自行测试吧。

将查询结果数据绑定到UI

2跟踪查询与非跟踪查询

在1小节生命周期里面我们有提及过跟踪与非跟踪查询,现在我们来了解下这两种查询区别。

21跟踪查询

返回实体类型的查询是默认会被跟踪的,这表示如果这些实体实例有更改行为,会通过SaveChanges()持久化将更改的值更新到数据库中,但是如果更改的值跟实体实例的值相同,则不会持久化提交数据到数据库,这就是跟踪查询。在以下示例中,将检测到对博客链接所做的更改,并在 SaveChanges() 期间将这些更改持久化到数据库中。

//返回blog实体类型的查询是默认会被跟踪

var blog = _contextBlogSingleOrDefault(b => bBlogId == 1);

//检测对博客链接所做的更改

blogUrl = "1";

//持久化保存到数据库中

_contextSaveChanges();

实体初始链接值是1,当我们点击Save按钮保存的时候,检测到对博客链接所做的更改值还是1的时候,并不会提交更改值到数据库中的。看看下图SQL Server Profiler监控就知道,并没有监控到对应有更新的T-SQL语句,也就是说并没有执行更新 *** 作:

当我们再把链接值更改为2点击保存时候,EF Core检测到博客链接值已经从1更改为2,就会持久化保存到数据库中。

blogUrl = "2";

废话少说,直接上图:

22非跟踪查询

如果不需要更新从数据库中检索到的实体,则应使用非跟踪查询。可以将单个查询替换为非跟踪查询。

var blogs = contextBlogs

//不用跟踪查询

AsNoTracking()

ToList();

//或者在上下文实例级别更改默认跟踪行为

contextChangeTrackerQueryTrackingBehavior = QueryTrackingBehaviorNoTracking;

var blogs = contextBlogsToList();

还是一样老谭秘方事例,当你加上非跟踪查询标识后,无论怎么更改博客链接值,都不会持久化保存数据到数据库中的。

var blogs = _contextBlog

//不用跟踪查询

AsNoTracking()

SingleOrDefault(m => mBlogId == 1);

blogsUrl = "2";

_contextSaveChanges();

直接上图跟踪结果:

在这相信大家从该小节跟踪与非跟踪查询中事例描述中总算对1小节查询生命周期有一定理解吧。

23跟踪和自定义投影

即使查询的结果类型不是实体类型,默认情况下EF Core也会跟踪结果中包含的实体类型。在以下返回匿名类型的查询中,结果集中的Blog实例会被跟踪。

var blog = contextBlogs

Select(b =>

new

{

Blog = b,

PostCount = bPostsCount()

});

如果结果集包含来自LINQ组合的实体类型,EF Core将跟踪它们。

var blog = contextBlogs

Select(b =>

new

{

Blog = b,

Post = bPostsOrderBy(p => pRating)LastOrDefault()

});

如果结果集不包含任何实体类型,则不会执行跟踪。在以下查询中,我们返回匿名类型(具有实体中的某些值,但没有实际实体类型的实例)。查询中没有任何被跟踪的实体。

var blog = contextBlogs

Select(b =>

new

{

Id = bBlogId,

Url = bUrl

});

EF Core支持执行顶级投影中的客户端评估。如果EF Core具体化实体实例以进行客户端评估,则会跟踪该实体实例。此处,由于我们要将blog实体传递到客户端方法StandardizeURL,因此EF Core也会跟踪博客实例。

var blogs = contextBlogs

OrderByDescending(blog => blogRating)

Select(blog => new

{

Id = blogBlogId,

Url = StandardizeUrl(blog)

})

ToList();

public static string StandardizeUrl(Blog blog)

{

var url = blogUrlToLower();

if (!urlStartsWith(">

     LINQ to Entities 是 LINQ 中最吸引人的部分。它让你可以使用标准的 C# 对象与数据库的结构和数据打交道。使用 LINQ to Entities 时,LINQ 查询在后台转换为 SQL 查询并在需要数据的时候执行,即开始枚举结果的时候执行。LINQ to Entities 还为你获取的所有数据提供变化追踪,也就是说,可以修改查询获得的对象,然后整批同时把更新提交到数据库。

       LINQ to Entities 是 Entity Framework 的一部分并且取代 LINQ to SQL 作为在数据库上使用 LINQ 的标准机制。Entity Framework 是行业领先的对象-关系映射(ORM)系统。可以和多种数据库一起使用,并支持各种灵活、复杂的数据模型。

注:

       微软把开发的重点从 LINQ to SQL 转移到了 LINQ to Entities,并且宣布 LINQ to SQL 不再提供更新,LINQ to SQL 现在仍被支持单不推荐。

       LINQ to Entities 是一项令人印象深刻的技术,但对大多数开发人员而言只是一个小的进步。和 DataSet 一样,ASPNET 开发人员使用 LINQ 的查询特新远多于它的批量更新特性。这是因为通常 Web 应用程序的更新是单次的而不是批量的。他们更愿意在页面回发时立刻执行更新,同时可以获得原始值和新(更新)值,这使得通过 ADONET 命令提交更新更加方便。

       简而言之,LINQ to Entities 没有提供任何不能用 ADONET代码、自定义对象、LINQ to Objects 实现的特性,但是有时出于某些原因而需要考虑使用 LINQ to Entities:

更少的代码。不必编写查询数据库的 ADONET 代码,可以通过一个工具生成需要的数据类。

灵活的查询能力。不必拼凑 SQL 语句,而是使用 LINQ 查询模型。一致的查询模型可访问众多不同的数据源(从数据库到 XML)。

变更追踪以及批量更新。可以对查询的数据进行多项修改并提交批量更新,这不需要编写任何 ADONET 代码。

生成数据模型

       Entity Framework 依赖于一个数据模型来使用 LINQ to Entities 进行查询。表中的行被转换为 C# 对象的实例,表的列是这些对象的属性。数据库架构和数据模型对象的映射是 Entity Framework 的核心

       为了生成模型,右击 App_Code 目录,单击“添加新项”,“ADONET 实体数据模型”,设置创建的文件名称后(这里是 NorthwindModeledmx),单击“确定”。

       从一个已经存在的数据库生成模型,即微软的 Northwind 示例数据库。配置数据库连接,并可以选择表、视图、和存储过程。还可以选择使用复数还是单数形式的对象名(例如,Products 表的行被命名为 Product )、是否包含外键关系等。这里选择全部表并选中“所生成对象的单复数形式”。

       Visual Studio 会为你选择的数据库元素创建模型图,它显示了已经创建的映射对象、对象拥有的字段以及对象之间的关系。

       项目中新增了下面这两个文件:

NorthwindModeledmx:这个XML文件定义数据库模型的架构。

NorthwindModelDesignercs:这个C#代码文件包含数据模型的映射对象。

数据模型类

       我们将把大部分时间花在 NorthwindModelDesignercs这个文件上。因为它包含了我们要用于 LINQ to Entities 查询的数据类型。(这个文件会被数据模型重新生成,因此不应该也不必要手工去修改这个文件,你的修改会丢失。)

       打开该文件,可以看到有两段代码区域:Contexts 和 Entities 。

1 派生的对象上下文

       NorthwindModelDesignercs文件中定义的第一个类从 ObjectContext 派生,其名称是 NorthwindEntities 。这个类的构造函数连接到所生成模型的数据库,或者你也可以指定连接字符串连接到其他数据库(必须具有相同的架构,否则模型无法工作)。

       下面是一个简单的示例:

protectedvoidPage_Load(objectsender, EventArgs e)

{

NorthwindEntities db = newNorthwindEntities();

GridView1DataSource = dbProducts

2111 准备数据源

既然LINQ可以查询多种数据源和对象,这些对象可能是数组,可能是数据集,也可能是数据库,那么在使用LINQ进行数据查询时首先需要准备数据源。

1.数组

数组中的数据可以被LINQ查询语句查询,这样就省去了复杂的数组遍历。数组数据源示例代码如下所示。

string[] str = { "学习", "学习LINQ", "好好学习", "生活很美好" };

int[] inter = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };

数组可以看成是一个集合,虽然数组没有集合的一些特性,但是从另一个角度上来说可以看成是一个集合。在传统的开发过程中,如果要筛选其中包含“学习”字段的某个字符串,则需要遍历整个数组。

2.SQL Server

在数据库 *** 作中,同样可以使用LINQ进行数据库查询。LINQ以其优雅的语法和面向对象的思想能够方便的进行数据库 *** 作,为了使用LINQ进行SQL Server数据库查询,可以创建两个表,这两个表的结构如下所示。Student(学生表):

 S_ID:学生ID。

 S_NAME:学生姓名。

 S_CLASS:学生班级。

 C_ID:所在班级的ID。

上述结构描述了一个学生表,可以使用SQL语句创建学生表,示例代码如下所示。

USE [student]

GO

SET ANSI_NULLS ON

GO

SET QUOTED_IDENTIFIER ON

GO

CREATE TABLE [dbo][Student](

[S_ID] [int] IDENTITY(1,1) NOT NULL,

[S_NAME] [nvarchar](50) COLLATE Chinese_PRC_CI_AS NULL,

[S_CLASS] [nvarchar](50) COLLATE Chinese_PRC_CI_AS NULL,

[C_ID] [int] NULL,

CONSTRAINT [PK_Student] PRIMARY KEY CLUSTERED

(

[S_ID] ASC

)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF,

ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]

) ON [PRIMARY]

为了更加详细的描述一个学生所有的基本信息,就需要创建另一个表对该学生所在的班级进行描述,班级表结构如下所示。Class(班级表):

 C_ID:班级ID。

 C_GREAD:班级所在的年级。

 C_INFOR:班级专业。

上述代码描述了一个班级的基本信息,同样可以使用SQL语句创建班级表,示例代码如下所示。

USE [student]

GO

SET ANSI_NULLS ON

GO

SET QUOTED_IDENTIFIER ON

GO

CREATE TABLE [dbo][Class](

[C_ID] [int] IDENTITY(1,1) NOT NULL,

[C_GREAD] [nvarchar](50) COLLATE Chinese_PRC_CI_AS NULL,

[C_INFOR] [nvarchar](50) COLLATE Chinese_PRC_CI_AS NULL,

CONSTRAINT [PK_Class] PRIMARY KEY CLUSTERED

(

[C_ID] ASC

)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF,

ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]

) ON [PRIMARY]

上述代码在Student数据库中创建了一个班级表,开发人员能够向数据库中添加相应的信息以准备数据源。

3.数据集

LINQ能够通过查询数据集进行数据的访问和整合;通过访问数据集,LINQ能够返回一个集合变量;通过遍历集合变量可以进行其中数据的访问和筛选。在第9章中讲到了数据集的概念,开发人员能够将数据库中的内容填充到数据集中,也可以自行创建数据集。

数据集是一个存在于内存的对象,该对象能够模拟数据库的一些基本功能,可以模拟小型的数据库系统,开发人员能够使用数据集对象在内存中创建表,以及模拟表与表之间的关系。在数据集的数据检索过程中,往往需要大量的if、else等判断才能检索相应的数据。

使用LINQ进行数据集中数据的整理和检索可以减少代码量并优化检索 *** 作。数据集可以是开发人员自己创建的数据集也可以是现有数据库填充的数据集,这里使用上述SQL Server创建的数据库中的数据进行数据集的填充。

2112 使用LINQ

在传统对象查询中,往往需要很多的if、else语句进行数组或对象的遍历,例如在数组中寻找相应的字段,实现起来往往比较复杂,而使用LINQ就简化了对象的查询。由于前面已经准备好了数据源,那么就能够分别使用LINQ语句进行数据源查询。

1.数组

在前面的章节中,已经创建了一个数组作为数据源,数组示例代码如下所示。

int[] inter = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };

上述代码是一个数组数据源,如果开发人员需要从其中的元素中搜索大于5的数字,传统的方法应该遍历整个数组并判断该数字是否大于5,如果大于5则输出,否则不输出,示例代码如下所示。

using System;

using SystemCollectionsGeneric;

using SystemLinq; //使用必要的命名空间

using SystemText;

namespace _21_1

{

class Program

{

static void Main(string[] args)

{

string[] str = { "学习", "学习LINQ", "好好学习", "生活很美好" }; //定义数组

int[] inter = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };

for (int i = 0; i < interLength; i++) //遍历数组

{

if (inter[i] > 5) //判断数组元素的值是否大于5

{

ConsoleWriteLine(inter[i]ToString()); //输出对象

}

}

ConsoleReadKey();

}

}

}

上述代码非常简单,将数组从头开始遍历,遍历中将数组中的的值与5相比较,如果大于5就会输出该值,如果小于5就不会输出该值。虽然上述代码实现了功能的要求,但是这样编写的代码繁冗复杂,也不具有扩展性。如果使用LINQ查询语句进行查询就非常简单,示例代码如下所示。

class Program

{

static void Main(string[] args)

{

string[] str = { "学习", "学习LINQ", "好好学习", "生活很美好" }; //定义数组

int[] inter = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; //定义数组

var st = from s in inter where s > 5 select s; //执行LINQ查询语句

foreach (var t in st) //遍历集合元素

{

ConsoleWriteLine(tToString()); //输出数组

}

ConsoleReadKey();

}

}

使用LINQ进行查询之后会返回一个IEnumerable的集合。在上一章讲过,IEnumerable是NET框架中最基本的集合访问器,可以使用foreach语句遍历集合元素。使用LINQ查询数组更加容易被阅读,LINQ查询语句的结构和SQL语法十分类似,LINQ不仅能够查询数组,还可以通过NET提供的编程语言进行筛选。例如str数组变量,如果要查询其中包含“学习”的字符串,对于传统的编程方法是非常冗余和繁琐的。由于LINQ是NET编程语言中的一部分,开发人员就能通过编程语言进行筛选,LINQ查询语句示例代码如下所示。

var st = from s in str where sContains("学习") select s;

2.使用SQL Server

在传统的数据库开发中,如果需要筛选某个数据库中的数据,可以通过SQL语句进行筛选。在ADONET中,首先需要从数据库中查询数据,查询后就必须将数据填充到数据集中,然后在数据集中进行数据遍历,示例代码如下所示。

try

{

SqlConnection

con = new SqlConnection("server='(local)';database='student';uid='sa';pwd='sa'"); //创建连接

conOpen(); //打开连接

string strsql = "select from student,class where studentc_id=classc_id"; //SQL语句

SqlDataAdapter da = new SqlDataAdapter(strsql, con); //创建适配器

DataSet ds = new DataSet(); //创建数据集

int j = daFill(ds, "mytable"); //填充数据集

for (int i = 0; i < j; i++) //遍历集合

{

ConsoleWriteLine(dsTables["mytable"]Rows[i]["S_NAME"]ToString()); //输出对象

}

}

catch

{

ConsoleWriteLine("数据库连接错误"); //抛出异常

}

上述代码进行数据库的访问和查询。在上述代码中,首先需要创建一个连接对象进行数据库连接,然后再打开连接,打开连接之后就要编写SELECT语句进行数据库查询并填充到DataSet数据集中,并在DataSet数据集中遍历相应的表和列进行数据筛选。如果要查询C_ID为1的学生的所有姓名,有三个办法,这三个办法分别是:

 修改SQL语句。

 在循环内进行判断。

 使用LINQ进行查询。

修改SQL语句是最方便的方法,直接在SELECT语句中添加查询条件WHERE C-ID=1就能够实现,但是这个方法扩展性非常的低,如果有其他需求则就需要修改SQL语句,也有可能造成其余代码填充数据集后数据集内容不同步。

在循环内进行判断也是一种方法,但是这个方法当循环增加时会造成额外的性能消耗,并且当需要扩展时,还需要修改循环代码。最方便的就是使用LINQ进行查询,在Visual Studio 2008中提供了LINQ to SQL类文件用于将现有的数据抽象成对象,这样就符合了面向对象的原则,同时也能够减少代码,提升扩展性。创建一个LINQ to SQL类文件,直接将服务资源管理器中的相应表拖放到LINQ to SQL类文件可视化窗口中即可,如图21-1所示。

图21-1 创建LINQ to SQL文件

创建了LINQ to SQL类文件后,就可以直接使用LINQ to SQL类文件提供的类进行查询,示例代码如下所示。

linqtosqlDataContext lq = new linqtosqlDataContext();

var mylq = from l in lqStudent from cl in lqClass where lC_ID==clC_ID select l; //执行查询

foreach (var result in mylq) //遍历集合

{

ConsoleWriteLine(resultS_NAMEToString()); //输出对象

}

上述代码只用了很短的代码就能够实现数据库中数据的查询和遍历,并且从可读性上来说也很容易理解,因为LINQ查询语句的语法基本与SQL语法相同,只要有一定的SQL语句基础就能够非常容易的编写LINQ查询语句。

3.数据集

LINQ同样对数据集支持查询和筛选 *** 作。其实数据集也是集合的表现形式,数据集除了能够填充数据库中的内容以外,开发人员还能够通过对数据集的 *** 作向数据集中添加数据和修改数据。前面的章节中已经讲到,数据集可以看作是内存中的数据库。数据集能够模拟基本的数据库,包括表、关系等。这里就将SQL Server中的数据填充到数据集即可,示例代码如下所示。

try

{

SqlConnection

con = new SqlConnection("server='(local)';database='student';uid='sa';pwd='sa'"); //创建连接

conOpen(); //打开连接

string strsql = "select from student,class where studentc_id=classc_id"; //执行SQL

SqlDataAdapter da = new SqlDataAdapter(strsql, con); //创建适配器

DataSet ds = new DataSet(); //创建数据集

daFill(ds, "mytable"); //填充数据集

DataTable tables = dsTables["mytable"]; //创建表

var dslq = from d in tablesAsEnumerable() select d; //执行LINQ语句

foreach (var res in dslq)

{

ConsoleWriteLine(resField<string>("S_NAME")ToString()); //输出对象

}

}

catch

{

ConsoleWriteLine("数据库连接错误");

}

上述代码使用LINQ针对数据集中的数据进行筛选和整理,同样能够以一种面向对象的思想进行数据集中数据的筛选。在使用LINQ进行数据集 *** 作时,LINQ不能直接从数据集对象中查询,因为数据集对象不支持LINQ查询,所以需要使用AsEnumerable方法返回一个泛型的对象以支持LINQ的查询 *** 作,示例代码如下所示。

var dslq = from d in tablesAsEnumerable() select d; //使用AsEnumerable

上述代码使用AsEnumerable方法就可以让数据集中的表对象能够支持LINQ查询。

2113 执行LINQ查询

从上一节可以看出LINQ在编程过程中极大的方便了开发人员对于业务逻辑的处理代码的编写,在传统的编程方法中复杂、冗余、难以实现的方法在LINQ中都能很好的解决。LINQ不仅能够像SQL语句一样编写查询表达式,LINQ最大的优点也包括LINQ作为编程语言的一部分,可以使用编程语言提供的特性进行LINQ条件语句的编写,这就弥补了SQL语句中的一些不足。在前面的章节中将一些复杂的查询和判断的代码简化成LINQ应用后,就能够执行应用程序判断LINQ是否查询和筛选出了所需要的值。

1.数组

在数组数据源中,开发人员希望能够筛选出大于5的元素。开发人员将传统的代码修改成LINQ代码并通过LINQ查询语句进行筛选,示例代码如下所示。

var st = from s in inter where s > 5 select s; //执行LINQ查询

上述代码将查询在inter数组中的所有元素并返回其中元素的值大于5的元素的集合,运行后如图21-2所示。

图21-2 遍历数组

LINQ执行了条件语句并返回了元素的值大于5的元素。LINQ语句能够方便的扩展,当有不同的需求时,可以修改条件语句进行逻辑判断,例如可以筛选一个平方数为偶数的数组元素,直接修改条件即可,LINQ查询语句如下所示。

var st = from s in inter where (ss)%2==0 select s; //执行LINQ查询

上述代码通过条件(ss)%2==0将数组元素进行筛选,选择平方数为偶数的数组元素的集合,运行后如图21-3所示。

图21-3 更改筛选条件

2.使用SQL Server

在LINQ to SQL类文件中,LINQ to SQL类文件已经将数据库的模型封装成一个对象,开发人员能够通过面向对象的思想访问和整合数据库。LINQ to SQL也对SQL做了补充,使用LINQ to SQL类文件能够执行更强大的筛选,LINQ查询语句代码如下所示。

var mylq = from l in lqStudent from cl in lqClass where lC_ID==clC_ID select l; //执行LINQ查询

上述代码从Student表和Class表中筛选了C_ID相等的学生信息,这很容易在SQL语句中实现。LINQ作为编程语言的一部分,可以使用更多的编程方法实现不同的筛选需求,例如筛选名称中包含“郭”字的学生的名称在传统的SQL语句中就很难通过一条语句实现,而在LINQ中就能够实现,示例代码如下所示。

var mylq = from l in lqStudent from cl in lqClass where lC_ID==clC_ID where

lS_NAMEContains("郭") select l; //执行LINQ条件查询

上述代码使用了Contains方法判断一个字符串中是否包含某个字符或字符串,这样不仅方便阅读,也简化了查询 *** 作,运行后如图21-4和图21-5所示。

图21-4 简单查询 图21-5 条件查询

LINQ返回了符合条件的元素的集合,并实现了筛选 *** 作。LINQ不仅作为编程语言的一部分,简化了开发人员的开发 *** 作,从另一方面讲,LINQ也补充了在SQL中难以通过几条语句实现的功能的实现。从上面的LINQ查询代码可以看出,就算是不同的对象、不同的数据源,其LINQ基本的查询语法都非常相似,并且LINQ还能够支持编程语言具有的特性从而弥补SQL语句的不足。在数据集的查询中,其查询语句也可以直接使用而无需大面积修改代码,这样代码就具有了更高的维护性和可读性。

以上就是关于用LINQtoSQL创建Web应用系统(一)全部的内容,包括:用LINQtoSQL创建Web应用系统(一)、LINQ更新:找不到行或行已更改、efcore检测数据是不是创建等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/sjk/9726301.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-01
下一篇 2023-05-01

发表评论

登录后才能评论

评论列表(0条)

保存