本章我们研究LNQ to SQL以及它的后续版本 LINQ to Entity Framework(简称 LINQ to Entities)。 Entity Framework是微软为.NET设计的一套ORM,它建立在之前的 ADO. NET之上。

LINQ to Entities和 LINQ to Object最大的不同之处在于, LINQ to Entities会被转化为表达式树,最终再转化为SQL语句,访问数据库并取回数据,数据的类型为 IQueryable。 LINQ to Object则将査询表达式和方法语法转化为委托在本地执行,数据的类型为Enumerable。作一看,似乎前者麻烦很多,但由于操作可以先被编译器缓存下来,最后当正访问数据时,才生成SQL语句返回 IQueryable,因此, LINQ to Entities j返回的数据总是你所需要的。
14.1 IQueryable
IQueryable继承了 IEnumerable接口。 Queryable是一个静态类型,它集合了许多扩是方法,扩展的目标是 IQueryable和 IEnumerable。它令 IQueryable和 IEnumerable一样,拥有强大的査询能力。但是,和 Enumerable不同的是, Queryable的扩展方法传入表达式:

而 Enumerable的扩展方法,传人的则是泛型委托。 LINQ to Entities 基于 IQueryable。
C#提供了 AsQueryable方法,可以将IEnumerable转换为 IQueryable:

var seq= Enumerable.Range(0, 9).Tolist();
IEnumerable<int> seq2= seq.Where(o=>o >5);
IQueryables<int> seq3 =seq.Where(o=>o >4).Asqueryable();

反过来则可以调用 AsEnumerable方法,将 IQueryable转换为 IEnumerable。

14.2 IQueryables与 IEnumerable的异同
IQueryables继承自 IEnumerable,所以对于数据遍历来说,它们没有区别。两者都具有延迟执行的效果。但IQueryables的优势是有表达式树,所有对于 IQueryables的过滤和排序等操作,都会先缓存到表达式树中,只有当真正发生遍历的时候,オ会将表达式树由IQueryable执行最终转换为SQL,获取数据。而使用 IEnumerable,所有对于IEnumerable的过滤,排序等操作,都是在内存中发生的。也就是说,数据已经从数据库中获取到内存中,在内存中进行过滤和排序操作。
当数据源不在本地时,因为 IEnumerable查询必须在本地执行,所以执行查询前必须把所有的数据加載到本地。大部分时候,加载的数据有大量是我们不需要的无效数据,但是我们却不得不传输更多的数据,做很多无用功。而 IQueryables却总能只提供你所需要的数据,大大减少了传输的数据量。
使用 LINQPad我们可以看到编译器生成的SQL。指定语言为C# Program,数据库为Northwind.mdf,我们可以键人下面的代码:

void Main()
{//这是 IQueryablesvar list = Customers.where(c => c.Address.Contains(s));//这是 IEnumerableIEnumerable<Customers> list2 = Customers.AsEnumerable<Customers>().Where(c =>c.Address.Contains("s"));var a=list.First();var b=list2.First();
}

其中,最后两句代码通过取第一个值强迫査询运行(如果去掉的话,不会生成任何SQL)。我们按F5运行,然后从结果栏中选择SQL,即可看到两个SQL:第一条SQL对
应的是 IQueryables的SQL。这个SQL会在数据库中进行筛选(拥有一个 where子句,而且使用top关键字选择了第一条数据),最终只有一条数据回到本地。而第二条SQL对应的是 IEnumerable的查询,我们可以看到没有任何的筛选,所有的数据都会被捞回本地。代码如下:


当数据很多的时候,性能孰强孰弱已经十分明显了一一即使 LINQ to Entities需要多一层表达式树解析SQL,但它可以缓存所有的操作(上面的例子中,当取第一个值时,LNQto Entities缓存了之前筛选的操作,并将两项操作合二为一,生成最有效的SQL代码,捞回最少的数据),最终捞回的数据总是你所需要的。和数据库通信以及数据交换相比,本解析SQL的时间可以忽略不计,因此,如果数据量大, LINQ to Entities的性能将会更佳。
14.3数据库操作
14.3.1 弱类型实体集
如果不使用ORM,我们还可以选择用ADO.NET和数据库沟通。ADO.NET拥有连线和离线两种模式,下面的代码展示了如何连线并使用 DataReader从数据库中拿数据。相信大家一定都写过或者看过类似的代码:

//莛接到数据库
var conn= new SqlConnection("Data Source=xxx: Initial Catalog=Northwind; User ID=sa");
conn.Open();
//传入SQL语句
var cmd = new Sqlcommand("SELECT * FROM Customer WHERE CustomerID LIKE '%v%',conn);
using (var reader=cmd.ExecuteReader(Commandbehavior Closeconnection))
{//使用 DataReaderwhile(reader.Read()){//必须手动入列名,且列名的类型和Getxxx方法必须匹配var s = reader.Getstring(reader.Getordinal("CustomerID"));//或者这样做也行,获得第一列,但你要确定第一列一定是字符串类型s= reader. Getstring(0);}
}

如果是离线的方式,则是将数据装载到一个 Dataset/ DataTable中,然后在其他地方再遍历这个 Dataset/DataTable对象,这里就不展示代码了。
这是若于年前的经典模式,并广泛存在于三层架构的数据访问对象(Data Access Object,DAO)中。ADO.NET支持传入SQL语句和参数化查询,甚至还支特调Sql Server中的存储过程。因此,存储过程一度大行其道。无论是连线还是离线的方式,取出的资料都是弱类型的,因此,这样的做法有运行异常的可能。如果哪天数据库表的定义发生改变,我们无法知道程序什么地方会出错,而且,SOL语句的拼接也很容易出错。
使用这种方式开发时, SQL Server是标配。必须先在 SQL Server I中进行调试,确保获得正确的SQL语句之后,再编写C#代码,确定其生产的SQL语句和正确的语句一样。最后,还要小心翼翼地从结果集中取出列,一一确定使用不同的 Getxxx方法获得每个不同类型的列,如果列类型是int,使用 Getstring就会出错。

14.3.2 Entity Framework
ORM解决了弱类型的问题,使得所有运行时的错误提前到编译时,在第10章,我们已经实现了一个十分简单的ORM,所以,大家应该对这个概念不陌生。ORM在传统的通过SOL访问数据库的方法上面增加了两层:
ロAPI:暴露给用户使用,并使用某种方式将API转化为SQL,我们实现的ORM用字符串拼接法转化SQL。
ロ Mapping:将C#实体类型(cs文件)和数据库表对应起来,我们实现的0RM使用了反射和特性做对应。
ロ 通过SQL访问数据库,我们实现的ORM中,最后还是用ADO.NET访问了数据库。

所有的ORM无论怎么实现,最后肯定还是要通过SQL访问数据库,差别仅在于生成SQL的方法和效率。 Entity Framework是微软提供的ORM,它的“ORM三层架构”分别是:
1)API,又分为三层。
a) LINQ to Entities,用户使用它下命令,传入的命令是表达式树并会被缓存起来。
b) Object Services,围绕 Dbcontext,暴露一部分有用的API让用户调用,包括新增、修改和删除记录,支持将更改存人数据库,并且提供了 实体的状态和变更追踪功能。
c) Entity SQL Service,将表达式树转化为SQL。用户也可以直接访问它并传人SQL,不过这里不支持新增修改和删除记录,这是 Obiect Servic该做的事情。通常来说,不应该直接在这里传人SQL,而应该使用上面两层。
2) Mapping, Entity Data Model负责将C#实体和数据库表对应起来。
3)通过SQL访问数据库,用ADO.NET。
因此, Entity Framework基于 ADO. NET之上。和LINQ相结合, Entity Framework可将LINQ指令转換为SQL语句(当然会有失败的情况),这些指令转换大部分时候的效能都是有保证的。Entity Framework也支持其他很多资料管理系统,例如 Oracle, MYSQL等。
下面,我门着重看看 Entity Framework的上面两层(第三层就是ADO.NET)。
1.Mapping层:Entity Data Model
Entity Framework使用 Entity Data Model将C#排实体和数据库表对应起来。它支持双向转化:
口读取C#实体代码,并在SQL Server中建立全新的数据库(Code First)。Entity Framework4.1之后开始支持。
口读取观成的数据库,生成全新的C#实体代码( Database First)。
口利用 Visual Studio提供的可视化工具,先建立数据库表定义,然后再根据定义生成实体( Model First)和数据库表。 Entity Framework4.0之后开始支持。
Entity Data Model实现了将C#s实体转换为数据库可以处理的形式,并作为 LINQ to Entities的基础。简单来说,它主要做下面几件事。
口描述每个C#实体中每个属性的数据类型和约束,以及实体之间的关系:通过最上层的概
概念纲要定义语言(CSDL).
口将C#实体和数据库表格打通:通过中间的 mapping schema(MSDL)。
口描述数据库表格中每个表格的数据类型和约東,以及表格之间的关系:通过最下层的纲要定义语言(SSDL)。
这样,C#实体就和实际数据库中的表格对应起来了。这三个语言都是以XML的形式,并抱合在一个.edmx文件中。不过,使用 Code First的形式不会导致.edmx文件的产生,整个实体一表格的映射通过代码完成。
2.API层
Entity SQL Service介于 Entity Data Model之上,它将下面的 Mapping层隔离开来,又作为上面 Object Service和 LINQ to Entities的基石。因此,对于程序员来说,完全可以把Entity SQL Service看成是实际数据库,它接受上层传来的查询,然后往下送到 Mapping层。
Object Service是在 Entity SQL Service之上的服务,负责 Dbcontext E的状态跟踪、新建和删除。 Object Service的核心围绕 Dbcontext对象,它提供了很多方法作为 LINQ to Entities的重要补充,例如对表格中记录的添加和删除、执行SQL指令、执行存储过程、将之前对数据库的更改保存起来等等。
位于最顶上的服务就是 LINQ to Entities,它围绕着 Dbset对象。EF中每一个表格都对应一个 Dbset,它实现了 IEnumerable,所以它也具有 LINQ to Object的查询指令。LNQ to Entities主要是负责查询的,对资料的增删改需要通过 Object Service I的方法来实现。
3.Unit of work
Unit of work是一种模式,它和事务配合,确保一连串对数据的改动要么全部发生,要么都不发生。通过 Dbcontext 的 SaveChange等方法,EF天生就具有 Unit of wor水模式。

和 Unit of work相对的就是数据访问对象(DAO)模式了,它不具备将一连串数据的改动组合起来的能力,当业务逻辑层访问数据层时,一次通常只会执行一条CRUD查淘。如果要实现将多条查询打包并使用事务管理,只能为每个组合建立专门的方法,或者使用存储过程。
14.3.3 Repository模式
与数据库中的数据沟通时,不同的功能需要实现不同的数据库访问逻辑。以前的三层架构中,业务逻辑层负责和下面的数据层沟通,并得到想要的数据,传给上面的应用层。在没有ORM之前,数据访问代码量十分庞大,因此,将访问隔离成层的想法是很自然的,效果也很好。
Repository(仓储)模式改进了业务逻辑层,并存在于业务逻辑层和数据层之间。它实现了一个仓库包裹器,使得对仓库的访问不会立刻提交到数据库,直到调用了仓库包裹器为止(即 Unit of work),然后,仓库包裹器就如同事务提交一般将所有数据库操作一并提交给数据库。Repository是仓库管理员,上层需要什么东西只需告诉仓库管理员,由仓库管理员把东西拿给它,而不需要知道东西实际放在哪。
使用 Repository模式的以下几点好处:
口方便单元测试。
口通过依赖注入实现ORM本身的置换。
口Unit of work
而现在使用EF之后,数据层基本上可以说是一键搞定了,上面的应用层也可以使用很简短的 Lambda表达式来直接访问数据,似乎仓储模式变得没有必要了,是这样吗?在网络上经常可以看到这种类似的讨论。对于小型工程,ORM完全可以替代仓储模式,首先,ORM本身的置换发生概率是非常低的;其次,EF本身已经实现了仓库包裹器(它的Dbcontext就是),不需要自行再实现一次。拿掉仓储模式之后,单元测试并不是不能做,只不过测试对象变成了上层方法而已。
14.4使用 LINQ to Entity Framework
说完 Entity Framework的概念之后,我们就在实际项目中使用一下吧。
14.4.1 Database First
Database First是指当数据库已经建立完成并有数据之后,在C#进行操作的方式。相比其他两种方式,它最容易理解。我们仍然使用第13章使用过的 Northwind演示数据库。
首先建立一个新的工程,然后为工程新加入一个ADO.NET实体数据模型,如图14-1所示。

我门将该.edmx文件命名为 Northwind。之后,进入实体数据模型向导。在这里,我们4个选项。
口自数据库的EF设计器:对应 Database First模式。
口空EF设计器模型:对应 Model First模式。
口Code First模型:对应 Code First模式。
口来自数据库 Code First:另一种 Code First模式。
这里我们选择第一项,再选择 SQL Server Database File,这样,就可以直接装载一个.mdf文件了,如图14-2所示。

选择演示数据库 Northwind之后(使用 Windows身份验证),IDE自动生成连接字符串和数据库上下文的名称,见图14-3。

之后,如果出现选择版本,请选择实体框架6.0。下一步是选择你要包含进去的表格和存储过程等。你不必在这里选择全部表格,在创建实体数据模型之后,也有机会为模型加入和删除表格,见图14-4。

其中,有三个选项,意义如下:
口对象名称単复数形式,例如,表的名称为 Orders,如果选择了这个选项,那么该表的记灵对应的实体将为 Order。如果不选择,则对应的实体名称和表名相同。这里我们不选。
口加入外键,通常都选择。
口加人存储过程和函数,视项目情况选择。
我们选择进项2和3,点击完成按钮之后,工程多了ー个.edmx文件,即是上面说到的三层定义文件。可以通过可视化工具观察.edmx文件的内容(图14-5显示了一部分)。

而 Model First,实际上就是通过IDE手动建立出这张表,而非从数据库导入。这非常烦,如果公司有数据库管理员,那么可以让数据库管理员使用SQL建立数据库,然后再用 Database First。如果使用 Model First,数据库管理员或开发者自己需要熟悉如何使用Visual Studio的可视化工具建立,edmx文件。.edmx文件内容繁多,它包括了数据库中我们选择的表格对应的所有实体,如图146所示。

每个实体的类型都是 Dbset。我们对实体的增删改查操作都是通过这个对象来进行的。面整个数据库则对应一个NorthwindEntities类,它是一个 Dbcontext。 Dbcontext和Dbset是 LINQ to Entities I的核心。由于 Dbsets继承了 IQueryable,所以大都分LINQ To Object的查询 Dbset也都具有(还记得IQueryable继承了 Ienumerable吗? 而Enumerable 扩展了 IEnumerable)。
现在我们就可以通过 LINQ to Entities对数据库进行操作了。注意所有的数据库都包含在数据库上下文之中,即 Northwindentities这个 Context对象。下面是一个简单的演示:

using (NorthwindEntities context =new Northwindentities())
{var customer =context.Customers.First();Console.Writeline(customer .Companyname);
}
 得到 context之后,就可以使用API层的中间层-Object Service,对数据库进行编辑。代码的第二行中,访问了 context多个表格中的一个 Customers,它在C#中是以DbSet<T>的形式存在的。 LINQ to Entities可以对 Dbset<T>进行查询。EF不是本书的重点,因此不会详细介绍EF的各种查询,有兴趣的读者可以自行到MSDN或其他网站学习。而且,由于EF的核心 Iqueryable继承了 IEnumerable,所以大部分 LINQ To Object 的查询仍然可以使用。

14.4.2 Model First
Model First是当还没有设计出数据库时,就在IDE中开始工作的方式,开发者通过IDE的可视化工具设计数据库编辑.edmx文件(拖拽表格并加入列和约束)。在添加新的ADO. NET实体资料模型时,选择“空EF设计器模型”,然后就可以打开一个可视化的设计面板,如图14-7所示:


我们以往上抱各种物体,例如实体、关联等。拖了一个实体之后,就可以往上加人列。在右边的属性列表中可以设定列的各种属性。
当全部完成后,单击右键选择“根据模型生成数据库”,就会产生一个 Context,当DBContext出现时,真正的数据库中也会相应地建立这些表格(即,将我们本来在S0L Server中做的工作转移到了Visual Studio 中来做)。我们可以保存这些建立表格的SQL脚本以便以后查阅。
和其他两种方式相比,这种方式使用的比较少。
14.4.3 Code First
对Model First模式来说,可能程序员还是觉得有些别扭,因为程序员比较习惯通过敲代码而不是拖拽控件的方式来生产数据库表。所以 Code First将产生数据库的方式从可视化的方送变成了自己写代码。
我们还是从新建ADO.NET实体数据模型开始,使用默认名称 Model。在向导中,第三个选项对应的就是Code First,如图14-8所示,如果你看不到这个选项,你需要下载对应的工具:https://www.microsoft.com/en-us/download/details.aspx?id=40762

选择空的 Code First 模型之后,系统将在 app.config中加入默认的资料库类型和连线字符串。系统还为我们生成了一个s文件,如图14-9所示。

现在我们在主程序中加入:

using (Modell context new Modell())
{context.Database.CreateIfNotExists():
}

即可完成数据库的创建。我们运行程序,然后查看一下 SQL Server对象资源管理,如图14-10所示。

我们看到一个新表 Myentities,含有两列Id和Name。而数据库创建的位置是根据连接字符串所确定的。
若要从现有数据库中产生 Code First模型,也可以在ADO.NET实体数据模型向导中选择来自数据库的 Code First.这就是将数据库中所有的数据列的属性约束以及数据表格之间的关联统统翻译成C#代码的过程。、
通过 Code First模式中丰富的API,C#代码可以表达各种各样的表格以及它们之间的关系,例如主键、外键、约束、一对多、多对多等。对 Entity Framework Code First的详细介绍超出了本书的范围,有兴趣的读者可以自行去网上寻找相关的资料。
14.5表达式树转化为SOL
在第13章中,我们解释了LNQ是如何将各种C#的语法特性结合在一起的,读者现应该可以使用原始方式对 IEnumerable进行査询了。那么, IQueryable可以手动实现吗?当然也是可以的,不过做法要复杂很多。
我们可以通过一个简单的例子一一实现一个非常简单的查询提供器,将简单的Where子句 Lambda表达式树转换为SQL。我们继续使用 Northwind做数据源。本节的代码在ExpTreeToSQL项目中。要使代码成功运行,需要手动建立数据库。
14.5.1 准备工作
我们需要明确一下我们要做的事情:
1)想办法将Where子句 Lambda表达式树转换为SQL。
2)接数据库并传人SQL,获得结果。
通过这两步,我们至少在 Where子句上可以取代LINQ to Entities。为了绕过整个EF,我们先使用SQL Server对象管理器在本地新建一个数据库testDatabase,如图14-11。

使用下面的SQL脚本建立一个新的表格:

CREATE TABLE [dbo].[Person]([Id] INT identity NOT NULL PRIMARY KEY,[Name] nvarchar(max) not null,[Age] int not null,[Sex] nvarchar(50) not null)
 右键点击表目录,添加新表,然后键人SQL,点击更新按钮即可执行SQL,建立表格如14-12所示。


表格建立好之后,从 SQL Server对象资源管理器中点击 testDatabase,查看属性、即可获得它的连接字符串。
最后,写一个简单的 Dbhelper类和对应的实体类,使用ADO.NET获取数据:

public class Dbhelper:IDisposable
{private SqlConnection _conn;public bool connect(){_conn= new SqlConnection{ConnectionString="Data Source=(localdb)\\Projects;Initial Catalog=TestDataBase;Integrated Security=True;Connect Timeout=30;};_conn.Open();return true;}Encrypt=False:public void Executesql (string sql){var cmd =new Sqlcommand(sql, _conn);cmd.ExecuteNonQuery();}public List<Person> Getperson(string sql){var person= new List<Person>();var cmd =new SqlCommand(sql,_conn);var sdr=cmd.Executereader();while(sdr Read()){person.Add(new Person{ID= sdr.Getint32(0),Name= sdr.Getstring(1),Age= sdr.Getint32(2),sex= sdr.Getstring(3)});}return person}public void Dispose(){_conn.Close();_conn=null;}
}
public class Person
{public int ID {get; set;}public string Name {get: set}public int Age {get: set:}public string Sex{get;set;}
}

现在我们可以连接数据库并传入SQL,获得结果。我们剩下的工作是传入表达树,并将表达式树解析为SQL。我们知道 LINQ to Entities拿回来的数据是 DbSet,它继承 IQueryable,因此,我们需要自己实现一个类继承 IQueryable,并建立一个实例,使得编译器改走我们的解析路线。

14.5.2 实现IQueryable
首选,我们自建一个类别Mylqueryable,继承 IQueryable。因为 IQueryable继承了IEnumerable,所以我们一样要实现GetEnumerator方法( IQueryable自身没有任何其他的方法需要实现,是一个空的接口)。只有当表达式需要计算时,才会调用
GetEnumerator方法(例如纯 Select就不会),这是延迟执行的特点,之前已经讨论过。然后,我门为IQueryable添加3个属性。
口 Expression:这个很好理解,就是要处理的表达式
口 Type:T的类型。
口 IQueryprovider:你自已的 Iquery Provider。在构造函数中,需要传人自己的IQueryprovider来实现自己的逻辑。
代码如下:

class Program
{static void Main(string[] args){using(var context=new NorthwindEntities()){//这是 Dbset< customers>,继承了 IQueryable<Customers>DbSet<Customers> customer= context.Customers;var list =customer.Where(c=> C Address Contains("s"));//这是自己的 My Iqueryable<Customersvar a= new MyIQueryable<Customers>();a.Where(t=>t Address Contains("s"));}Console.ReadKey();}
}
public class MyIQueryable<T>: IQueryablest<T>
{public IEnumerable<T> Get Enumerator(){throw new Not Implementedexception();}IEnumerator Ienumerable. GetEnumerator(){return GetEnumerator();}public Expression Expression {get: private set;}public Type ElementType{get, private set:}public IQueryProvider Provider {get: private set;}/  //不知道该写什么的构造函数public Myiqueryable(){}
}

如果现在运行程序,将会报错,因为我们的 MyIQueryable的所有属性都是null,类型没有意义。我们需要实现构造函数和 Getenumerator方法,并提供属性的值。
14.5.3实现 IQueryProvider
IQueryable必须有 IQueryProvider オ能工作。所以我们要写一个 IQueryProvider ,然后在构造函数中传入。我们再次新建一个类型,继承 Iquery Provider,此时我们又需要实现4个方法,其中非泛型版本的两个方法可以暂时不用理会。代码如下:

public class MyQueryProvider:IQueryProvider
{public IQueryable CreateQuery(Expression expression){throw new NotImplementedException();}public IQueryable <TElement> CreateQuery<Telement>(Expression expression){throw new NotImplementedException();}public object Execute(Expression expression){throw new NotImplementedException();}public TResult Execute<TResult >(Expression expression){throw new NotImplementedException();}
}

IQueryProvider将会做如下事情:
口 CreateQuery建立一个查询,但不计算,只在需要的时候才进行计算。
口 如果需要执行表达式的计算(例如调用了 ToList),此时调用 IQueryable的Getenumerator,它调用 Execute计算表达式。所以我们需要把自己的逻辑写在Execute方法中,并在 Getenumerator中进行调用。

第14章 LINQ to SOL相关推荐

  1. 《Kotin 极简教程》第14章 使用 Kotlin DSL

    第14章 使用 Kotlin DSL 最新上架!!!< Kotlin极简教程> 陈光剑 (机械工业出版社) 可直接打开京东,淘宝,当当===> 搜索: Kotlin 极简教程 htt ...

  2. 第13章 LINQ to Object

    第13章 LINQ to Object 在第12章,我们学习了很多C#3的新特性,包括匿名类型.扩展方法.隐式类型等,而这些新特性都是为LNQ服务的. LINQ to Object将查询语句转换为委托 ...

  3. www服务器提供的第一个信息页面,第14章WWW服务

    <第14章WWW服务>由会员分享,可在线阅读,更多相关<第14章WWW服务(48页珍藏版)>请在人人文库网上搜索. 1.第14章 WWW服务,学习本章应掌握: WWW服务系统中 ...

  4. 老李推荐:第14章4节《MonkeyRunner源码剖析》 HierarchyViewer实现原理-装备ViewServer-端口转发 1...

    老李推荐:第14章4节<MonkeyRunner源码剖析> HierarchyViewer实现原理-装备ViewServer-端口转发 在初始化HierarchyViewer的实例过程中, ...

  5. 【书评:Oracle查询优化改写】第14章 结尾章

    [书评:Oracle查询优化改写]第14章 结尾章 一.1  相关参考文章链接 前13章的链接参考相关连接: [书评:Oracle查询优化改写]第一章 http://blog.itpub.net/26 ...

  6. Windows2008管理---第14章 高可用群集和QoS

    第14章 高可用群集和QoS 目录 第1章 高可用群集和QoS. 1<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com ...

  7. 第14章 SpringBoot静态资源处理

    第14章 SpringBoot静态资源处理 14.1 WebMvcAutoConfiguration的默认配置 14.2 自定义静态资源映射 14.3 前端资源的引用方法

  8. 【机器学习实战】第14章 利用SVD简化数据

    第14章 利用SVD简化数据 SVD 概述 奇异值分解(SVD, Singular Value Decomposition):提取信息的一种方法,可以把 SVD 看成是从噪声数据中抽取相关特征.从生物 ...

  9. 【控制】《多智能体系统一致性协同演化控制理论与技术》纪良浩老师-第14章-带通信和输入时延的异构竞争多智能体系统分组一致性

    第13章 回到目录 第15章 第14章-带通信和输入时延的异构竞争多智能体系统分组一致性 14.1 引言 14.2 预备知识 14.3 问题描述与分析 14.4 例子与数值仿真 14.5 本章小结 1 ...

最新文章

  1. 【Foundation Frame】NSDictionary/NSMutableDictionary
  2. memmove函数使用时注意的问题
  3. web 应用常见安全漏洞一览
  4. Hyperloop,让发布简洁高效
  5. shell倒数第三位增加字符_shell中常用的变量处理、字符串操作(之三)
  6. 爬虫 requests模块的其他用法 抽屉网线程池回调爬取+保存实例,gihub登陆实例
  7. 传智播客 网络通信过程学习笔记
  8. 计算机游戏程序启动错误及其解决方法汇总
  9. 新浪云HTML播放音乐,音乐播放器-html代码
  10. java ip地址定位,Java根据IP地址定位位置
  11. python数据笔记分析_python数据分析入门学习笔记
  12. 人人互动直播之Swoole通讯服务重启教程
  13. 使用苹果的地图与定位
  14. 点击button没有反应
  15. 广东未来科技AI立体数码相机:因细节而闪耀
  16. 前端js华为云obs上传下载文件与进度条的设置
  17. Fiddler工具基础使用(web端抓包)
  18. 一款可编程的的串口调试工具 报文分类 脚本编程
  19. bt云服务器地址,windows服务器使用BT搭建环境
  20. XCode 7 官方直接下载地址

热门文章

  1. hp打印机没连上计算机,有关如何将HP打印机连接到计算机,如何添加打印机的详细步骤-...
  2. jdbc连接MysQL数据库时报错:The server time zone value ‘ ‘ is unrecognized or represents more than
  3. 物联网技术概论:第1章
  4. 浏览器的储存方式有哪些
  5. 读书笔记:《浪潮之巅:下》
  6. Windows11专业版安装USBCAN-II驱动后报错“……无法加载这个硬件的设备驱动程序……(代码39)”解决方案
  7. CWS(美国国土安全部下属的软件保证项目)与SANS(权威安全培训组织)联合编制的最危险的25个编程错误
  8. python3 pycharm 抓取app 上的数据
  9. Android最新最全100余款开源App(对应Github开源项目)
  10. 帮助新员工快速形成战斗力,Filez在入职与培训场景应用