Entity Framework Core allows you to use the navigation properties in your model to load related entities. There are three common O/RM patterns used to load related data.

  • Eager loading means that the related data is loaded from the database as part of the initial query.
  • Explicit loading means that the related data is explicitly loaded from the database at a later time.
  • Lazy loading means that the related data is transparently loaded from the database when the navigation property is accessed.
Tip
You can view this article's sampleon GitHub.

Eager loading


You can use the Include method to specify related data to be included in query results. In the following example, the blogs that are returned in the results will have their Posts property populated with the related posts.

using (var context = new BloggingContext())
{
var blogs = context.Blogs
.Include(blog => blog.Posts)
.ToList();
}
Tip
Entity Framework Core will automatically fix-up navigation properties to any other entities that were previously loaded into the context instance. So even if you don't explicitly include the data for a navigation property, the property may still be populated if some or all of the related entities were previously loaded.

You can include related data from multiple relationships in a single query.

using (var context = new BloggingContext())
{
var blogs = context.Blogs
.Include(blog => blog.Posts)
.Include(blog => blog.Owner)
.ToList();
}

Including multiple levels
You can drill down through relationships to include multiple levels of related data using the ThenInclude method. The following example loads all blogs, their related posts, and the author of each post.

using (var context = new BloggingContext())
{
var blogs = context.Blogs
.Include(blog => blog.Posts)
.ThenInclude(post => post.Author)
.ToList();
}
Note
Current versions of Visual Studio offer incorrect code completion options and can cause correct expressions to be flagged with syntax errors when using the ThenInclude method after a collection navigation property. This is a symptom of an IntelliSense bug tracked at https://github.com/dotnet/roslyn/issues/8237. It is safe to ignore these spurious syntax errors as long as the code is correct and can be compiled successfully.

You can chain multiple calls to ThenInclude to continue including further levels of related data.

using (var context = new BloggingContext())
{
var blogs = context.Blogs
.Include(blog => blog.Posts)
.ThenInclude(post => post.Author)
.ThenInclude(author => author.Photo)
.Include(blog => blog.Owner)
.ThenInclude(owner => owner.Photo)
.ToList();
}

You can combine all of this to include related data from multiple levels and multiple roots in the same query.

using (var context = new BloggingContext())
{
var blogs = context.Blogs
.Include(blog => blog.Posts)
.ThenInclude(post => post.Author)
.ThenInclude(author => author.Photo)
.Include(blog => blog.Owner)
.ThenInclude(owner => owner.Photo)
.ToList();
}

You may want to include multiple related entities for one of the entities that is being included. For example, when querying Blogs, you include Posts and then want to include both the Author and Tags of the Posts. To do this, you need to specify each include path starting at the root. For example, Blog -> Posts -> Author and Blog -> Posts -> Tags. This does not mean you will get redundant joins, in most cases EF will consolidate the joins when generating SQL.

using (var context = new BloggingContext())
{
var blogs = context.Blogs
.Include(blog => blog.Posts)
.ThenInclude(post => post.Author)
.Include(blog => blog.Posts)
.ThenInclude(post => post.Tags)
.ToList();
}

Include on derived types
You can include related data from navigations defined only on a derived type using Include and ThenInclude.
Given the following model:

public class SchoolContext : DbContext
{
public DbSet<Person> People { get; set; }
public DbSet<School> Schools { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<School>().HasMany(s => s.Students).WithOne(s => s.School);
}
} public class Person
{
public int Id { get; set; }
public string Name { get; set; }
} public class Student : Person
{
public School School { get; set; }
} public class School
{
public int Id { get; set; }
public string Name { get; set; } public List<Student> Students { get; set; }
}

Contents of School navigation of all People who are Students can be eagerly loaded using a number of patterns:

  • using cast
context.People.Include(person => ((Student)person).School).ToList()
  • using as operator
context.People.Include(person => (person as Student).School).ToList()

using overload of Include that takes parameter of type string

context.People.Include("Student").ToList()

Ignored includes
If you change the query so that it no longer returns instances of the entity type that the query began with, then the include operators are ignored.
In the following example, the include operators are based on the Blog, but then the Select operator is used to change the query to return an anonymous type. In this case, the include operators have no effect.

using (var context = new BloggingContext())
{
var blogs = context.Blogs
.Include(blog => blog.Posts)
.Select(blog => new
{
Id = blog.BlogId,
Url = blog.Url
})
.ToList();
}

By default, EF Core will log a warning when include operators are ignored. See Loggingfor more information on viewing logging output. You can change the behavior when an include operator is ignored to either throw or do nothing. This is done when setting up the options for your context - typically in DbContext.OnConfiguring, or in Startup.cs if you are using ASP.NET Core.

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder
.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=EFQuerying;Trusted_Connection=True;ConnectRetryCount=0")
.ConfigureWarnings(warnings => warnings.Throw(CoreEventId.IncludeIgnoredWarning));
}

Explicit loading


 
Note
This feature was introduced in EF Core 1.1.

You can explicitly load a navigation property via the DbContext.Entry(...) API.

using (var context = new BloggingContext())
{
var blog = context.Blogs
.Single(b => b.BlogId == ); context.Entry(blog)
.Collection(b => b.Posts)
.Load(); context.Entry(blog)
.Reference(b => b.Owner)
.Load();
}

You can also explicitly load a navigation property by executing a separate query that returns the related entities. If change tracking is enabled, then when loading an entity, EF Core will automatically set the navigation properties of the newly-loaded entitiy to refer to any entities already loaded, and set the navigation properties of the already-loaded entities to refer to the newly-loaded entity.

Querying related entities

You can also get a LINQ query that represents the contents of a navigation property.

This allows you to do things such as running an aggregate operator over the related entities without loading them into memory.

using (var context = new BloggingContext())
{
var blog = context.Blogs
.Single(b => b.BlogId == ); var postCount = context.Entry(blog)
.Collection(b => b.Posts)
.Query()
.Count();
}

You can also filter which related entities are loaded into memory.

using (var context = new BloggingContext())
{
var blog = context.Blogs
.Single(b => b.BlogId == ); var goodPosts = context.Entry(blog)
.Collection(b => b.Posts)
.Query()
.Where(p => p.Rating > )
.ToList();
}

Explicit loading中Query方法后面的查询条件,是会动态生成数据库SQL的,例如下面的代码中,我们使用Query方法后,又使用了Where方法做筛选:

var category = context.Category.First();

context.Entry(category).Collection(e => e.CategoryLanguage).Query().Where(e => e.LanguageCode == "CN").Load();

那么我们可以通过EF Core的后台日志看到,其生成的SQL查询中相应地包含了我们上面Where方法的筛选条件:

=============================== EF Core log started ===============================
Executed DbCommand (213ms) [Parameters=[@__get_Item_0='?' (Size = 50)], CommandType='Text', CommandTimeout='0']
SELECT [e].[CategoryCode], [e].[LanguageCode], [e].[CategoryName], [e].[DataStatus], [e].[ID]
FROM [MD].[CategoryLanguage] AS [e]
WHERE ([e].[CategoryCode] = @__get_Item_0) AND ([e].[LanguageCode] = N'CN')
=============================== EF Core log finished ===============================

Lazy loading


Note
This feature was introduced in EF Core 2.1.

The simplest way to use lazy-loading is by installing the Microsoft.EntityFrameworkCore.Proxies package and enabling it with a call to UseLazyLoadingProxies. For example:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder
.UseLazyLoadingProxies()
.UseSqlServer(myConnectionString);

Or when using AddDbContext:

.AddDbContext<BloggingContext>(
b => b.UseLazyLoadingProxies()
.UseSqlServer(myConnectionString));

EF Core will then enable lazy loading for any navigation property that can be overridden--that is, it must be virtual and on a class that can be inherited from. For example, in the following entities, the Post.Blog and Blog.Posts navigation properties will be lazy-loaded.

public class Blog
{
public int Id { get; set; }
public string Name { get; set; } public virtual ICollection<Post> Posts { get; set; }
} public class Post
{
public int Id { get; set; }
public string Title { get; set; }
public string Content { get; set; } public virtual Blog Blog { get; set; }
}

Lazy loading 中又使用Eager loading


如果在启用Lazy loading后又使用了Include方法来使用Eager loading,那么实际上是Eager loading在起作用,这样EF Core实体的导航属性不会再单独开启数据库连接去数据库查询数据,而是用sql语句的join预先在数据库中查询数据:

假设我们现在有Person实体里面有个Book导航属性,返回ICollection<Book>类型来获取关联一个Person的所有Book数据,假如我们启用Lazy loading然后查询Person实体的Book导航属性,代码如下:

using (TestDBContext dbContext = new TestDBContext())
{
var p=dbContext.Person.First();
var books = p.Book;
}

查看EF Core的日志,我们发现会开启两个数据库连接做两次查询,第一次查询Person表的数据,第二次查询Book表的数据:

第一次数据库连接查询Person表的数据:

=============================== EF Core log started ===============================
Opening connection to database 'TestDB' on server 'localhost'.
=============================== EF Core log finished ===============================
“dotnet.exe”(CoreCLR: clrhost): 已加载“C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App\2.1.4\System.Text.Encoding.CodePages.dll”。已跳过加载符号。模块进行了优化,并且调试器选项“仅我的代码”已启用。
=============================== EF Core log started ===============================
Opened connection to database 'TestDB' on server 'localhost'.
=============================== EF Core log finished ===============================
=============================== EF Core log started ===============================
Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
SELECT TOP(1) [p].[Code], [p].[CreateTime], [p].[ID], [p].[Name], [p].[UpdateTime]
FROM [Person] AS [p]
=============================== EF Core log finished ===============================
“dotnet.exe”(CoreCLR: clrhost): 已加载“C:\Program Files\dotnet\shared\Microsoft.NETCore.App\2.1.4\System.Xml.ReaderWriter.dll”。已跳过加载符号。模块进行了优化,并且调试器选项“仅我的代码”已启用。
=============================== EF Core log started ===============================
Executed DbCommand (16ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
SELECT TOP(1) [p].[Code], [p].[CreateTime], [p].[ID], [p].[Name], [p].[UpdateTime]
FROM [Person] AS [p]
=============================== EF Core log finished ===============================
=============================== EF Core log started ===============================
A data reader was disposed.
=============================== EF Core log finished ===============================
=============================== EF Core log started ===============================
Closing connection to database 'TestDB' on server 'localhost'.
=============================== EF Core log finished ===============================
=============================== EF Core log started ===============================
Closed connection to database 'TestDB' on server 'localhost'.
=============================== EF Core log finished ===============================

第二次数据库连接,查询Book表的数据:

=============================== EF Core log started ===============================
Opening connection to database 'TestDB' on server 'localhost'.
=============================== EF Core log finished ===============================
=============================== EF Core log started ===============================
Opened connection to database 'TestDB' on server 'localhost'.
=============================== EF Core log finished ===============================
=============================== EF Core log started ===============================
Executing DbCommand [Parameters=[@__get_Item_0='?' (Size = 50)], CommandType='Text', CommandTimeout='30']
SELECT [e].[BookCode], [e].[BookName], [e].[ID], [e].[PersonCode]
FROM [Book] AS [e]
WHERE [e].[PersonCode] = @__get_Item_0
=============================== EF Core log finished ===============================
=============================== EF Core log started ===============================
Executed DbCommand (8ms) [Parameters=[@__get_Item_0='?' (Size = 50)], CommandType='Text', CommandTimeout='30']
SELECT [e].[BookCode], [e].[BookName], [e].[ID], [e].[PersonCode]
FROM [Book] AS [e]
WHERE [e].[PersonCode] = @__get_Item_0
=============================== EF Core log finished ===============================
=============================== EF Core log started ===============================
Context 'Book' started tracking 'TestDBContext' entity. Consider using 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see key values.
=============================== EF Core log finished ===============================
=============================== EF Core log started ===============================
Context 'Book' started tracking 'TestDBContext' entity. Consider using 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see key values.
=============================== EF Core log finished ===============================
=============================== EF Core log started ===============================
Context 'Book' started tracking 'TestDBContext' entity. Consider using 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see key values.
=============================== EF Core log finished ===============================
=============================== EF Core log started ===============================
A data reader was disposed.
=============================== EF Core log finished ===============================
=============================== EF Core log started ===============================
Closing connection to database 'TestDB' on server 'localhost'.
=============================== EF Core log finished ===============================
=============================== EF Core log started ===============================
Closed connection to database 'TestDB' on server 'localhost'.
=============================== EF Core log finished ===============================

现在我们修改代码如下,改为在Lazy loading下使用Include方法来结合Eager loading:

using (TestDBContext dbContext = new TestDBContext())
{
var p = dbContext.Person.Include(e => e.Book).First();
var books = p.Book;
}

我们再来查看EF Core的日志,发现这一次只开启了一次数据库连接,用sql语句的join直接把Person表和Book表的数据都查出来,说明这种情况下实际上是Eager loading在起作用:

=============================== EF Core log started ===============================
Opening connection to database 'TestDB' on server 'localhost'.
=============================== EF Core log finished ===============================
“dotnet.exe”(CoreCLR: clrhost): 已加载“C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App\2.1.4\System.Text.Encoding.CodePages.dll”。已跳过加载符号。模块进行了优化,并且调试器选项“仅我的代码”已启用。
=============================== EF Core log started ===============================
Opened connection to database 'TestDB' on server 'localhost'.
=============================== EF Core log finished ===============================
=============================== EF Core log started ===============================
Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
SELECT TOP(1) [e].[Code], [e].[CreateTime], [e].[ID], [e].[Name], [e].[UpdateTime]
FROM [Person] AS [e]
ORDER BY [e].[Code]
=============================== EF Core log finished ===============================
“dotnet.exe”(CoreCLR: clrhost): 已加载“C:\Program Files\dotnet\shared\Microsoft.NETCore.App\2.1.4\System.Xml.ReaderWriter.dll”。已跳过加载符号。模块进行了优化,并且调试器选项“仅我的代码”已启用。
=============================== EF Core log started ===============================
Executed DbCommand (21ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
SELECT TOP(1) [e].[Code], [e].[CreateTime], [e].[ID], [e].[Name], [e].[UpdateTime]
FROM [Person] AS [e]
ORDER BY [e].[Code]
=============================== EF Core log finished ===============================
=============================== EF Core log started ===============================
Context 'Person' started tracking 'TestDBContext' entity. Consider using 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see key values.
=============================== EF Core log finished ===============================
=============================== EF Core log started ===============================
A data reader was disposed.
=============================== EF Core log finished ===============================
=============================== EF Core log started ===============================
Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
SELECT [e.Book].[BookCode], [e.Book].[BookName], [e.Book].[ID], [e.Book].[PersonCode]
FROM [Book] AS [e.Book]
INNER JOIN (
SELECT TOP(1) [e0].[Code]
FROM [Person] AS [e0]
ORDER BY [e0].[Code]
) AS [t] ON [e.Book].[PersonCode] = [t].[Code]
ORDER BY [t].[Code]
=============================== EF Core log finished ===============================
=============================== EF Core log started ===============================
Executed DbCommand (5ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
SELECT [e.Book].[BookCode], [e.Book].[BookName], [e.Book].[ID], [e.Book].[PersonCode]
FROM [Book] AS [e.Book]
INNER JOIN (
SELECT TOP(1) [e0].[Code]
FROM [Person] AS [e0]
ORDER BY [e0].[Code]
) AS [t] ON [e.Book].[PersonCode] = [t].[Code]
ORDER BY [t].[Code]
=============================== EF Core log finished ===============================
=============================== EF Core log started ===============================
A data reader was disposed.
=============================== EF Core log finished ===============================
=============================== EF Core log started ===============================
Closing connection to database 'TestDB' on server 'localhost'.
=============================== EF Core log finished ===============================
=============================== EF Core log started ===============================
Closed connection to database 'TestDB' on server 'localhost'.
=============================== EF Core log finished ===============================

Lazy loading without proxies


Lazy-loading proxies work by injecting the ILazyLoader service into an entity, as described inEntity Type Constructors. For example:

public class Blog
{
private ICollection<Post> _posts; public Blog()
{
} private Blog(ILazyLoader lazyLoader)
{
LazyLoader = lazyLoader;
} private ILazyLoader LazyLoader { get; set; } public int Id { get; set; }
public string Name { get; set; } public ICollection<Post> Posts
{
get => LazyLoader.Load(this, ref _posts);
set => _posts = value;
}
} public class Post
{
private Blog _blog; public Post()
{
} private Post(ILazyLoader lazyLoader)
{
LazyLoader = lazyLoader;
} private ILazyLoader LazyLoader { get; set; } public int Id { get; set; }
public string Title { get; set; }
public string Content { get; set; } public Blog Blog
{
get => LazyLoader.Load(this, ref _blog);
set => _blog = value;
}
}

This doesn't require entity types to be inherited from or navigation properties to be virtual, and allows entity instances created with new to lazy-load once attached to a context. However, it requires a reference to the ILazyLoader service, which is defined in the Microsoft.EntityFrameworkCore.Abstractions package. This package contains a minimal set of types so that there is very little impact in depending on it. However, to completely avoid depending on any EF Core packages in the entity types, it is possible to inject the ILazyLoader.Load method as a delegate. For example:

public class Blog
{
private ICollection<Post> _posts; public Blog()
{
} private Blog(Action<object, string> lazyLoader)
{
LazyLoader = lazyLoader;
} private Action<object, string> LazyLoader { get; set; } public int Id { get; set; }
public string Name { get; set; } public ICollection<Post> Posts
{
get => LazyLoader.Load(this, ref _posts);
set => _posts = value;
}
} public class Post
{
private Blog _blog; public Post()
{
} private Post(Action<object, string> lazyLoader)
{
LazyLoader = lazyLoader;
} private Action<object, string> LazyLoader { get; set; } public int Id { get; set; }
public string Title { get; set; }
public string Content { get; set; } public Blog Blog
{
get => LazyLoader.Load(this, ref _blog);
set => _blog = value;
}
}

The code above uses a Load extension method to make using the delegate a bit cleaner:

public static class PocoLoadingExtensions
{
public static TRelated Load<TRelated>(
this Action<object, string> loader,
object entity,
ref TRelated navigationField,
[CallerMemberName] string navigationName = null)
where TRelated : class
{
loader?.Invoke(entity, navigationName); return navigationField;
}
}
Note
The constructor parameter for the lazy-loading delegate must be called "lazyLoader". Configuration to use a different name than this is planned for a future release. 蛋疼,现在构造函数的参数必须要叫lazyLoader这个参数名,期待上面说的 is planned for a future release吧。。。

Related data and serialization(ASP.NET Core MVC如何避免EF Core的Lazy loading开启后,实体在Json序列化时被循环引用,造成死循环)


Because EF Core will automatically fix-up navigation properties, you can end up with cycles in your object graph. For example, loading a blog and its related posts will result in a blog object that references a collection of posts. Each of those posts will have a reference back to the blog.
Some serialization frameworks do not allow such cycles. For example, Json.NET will throw the following exception if a cycle is encountered.

Newtonsoft.Json.JsonSerializationException: Self referencing loop detected for property 'Blog' with type 'MyApplication.Models.Blog'.

If you are using ASP.NET Core, you can configure Json.NET to ignore cycles that it finds in the object graph. This is done in the ConfigureServices(...) method in Startup.cs.

public void ConfigureServices(IServiceCollection services)
{
... services.AddMvc()
.AddJsonOptions(
options => options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore
); ...
}

可以看到ASP.NET Core MVC有很简单的机制,来防止EF Core开启Lazy loading后,其实体进行Json序列化时被循环引用造成死循环,AddJsonOptions方法中一个设置就搞定了,很智能。

原文链接

EF Core 2.1 中的 Eager loading、Explicit loading和LazyLoading (转自MSDN)的更多相关文章

  1. EF Core 1.0中使用Include的小技巧

    (此文章同时发表在本人微信公众号"dotNET每日精华文章",欢迎右边二维码来关注.) 题记:由于EF Core暂时不支持Lazy Loading,所以利用Include来加载额外 ...

  2. EF Core 2.0中如何手动映射数据库的视图为实体

    由于Scaffold-DbContext指令目前还不支持自动映射数据库中的视图为实体,所以当我们想使用EF Core来读取数据库视图数据的时候,我们需要手动去做映射,本文介绍如何在EF Core中手动 ...

  3. EF Core 2.0中Transaction事务会对DbContext底层创建和关闭数据库连接的行为有所影响

    数据库 我们先在SQL Server数据库中建立一个Book表: CREATE TABLE [dbo].[Book]( ,) NOT NULL, ) NULL, ) NULL, ) NULL, [Cr ...

  4. Lazy Loading | Explicit Loading | Eager Loading in EntityFramework and EntityFramework.Core

    EntityFramework Eagerly Loading Eager loading is the process whereby a query for one type of entity ...

  5. EF Core 2.0中怎么用DB First通过数据库来生成实体

    要在EF Core使用DB First首先要下载三个Nuget包,在Nuget的Package Manager Console窗口中依次敲入下面三个命令即可: Microsoft.EntityFram ...

  6. EF Core For Oracle11中Find FirstOrDefault等方法执行失败

    问题描述 最近在使用ef core连接oracle的发现Find.FirstOrDefault.Skip Task分页等等方法执行失败.使用的是docker安装的oracle11,错误如下图: 解决办 ...

  7. EF Core 2.0 新特性

    前言 目前 EF Core 的最新版本为 2.0.0-priview1-final,所以本篇文章主要是针对此版本的一些说明. 注意:如果你要在Visual Studio 中使用 .NET Core 2 ...

  8. EF Core中如何正确地设置两张表之间的关联关系

    数据库 假设现在我们在SQL Server数据库中有下面两张表: Person表,代表的是一个人: CREATE TABLE [dbo].[Person]( ,) NOT NULL, ) NULL, ...

  9. EF Core中如何设置数据库表自己与自己的多对多关系

    本文的代码基于.NET Core 3.0和EF Core 3.0 有时候在数据库设计中,一个表自己会和自己是多对多关系. 在SQL Server数据库中,现在我们有Person表,代表一个人,建表语句 ...

随机推荐

  1. hdu 4628 Pieces 状态压缩dp

    Pieces Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total S ...

  2. vsphere client 创建虚拟机 如何关联到本地iso文件

    问题:以前用过vmere 创建虚拟机,都要在虚拟机启动之前配置系统镜像文件,第一次使用vspere client时在创建虚拟机后,我就想着应该先配置,再启动,其实,非也,应该这样,先启动虚拟机,在点按 ...

  3. Git版本控制工具(1)

    学习Git的最佳资料网站: https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000/ 这 ...

  4. shell脚本报错 value too great for base

    此错误是shell脚本在计算以0开头的数字时,默认以8进制进行计算,导致在计算08时超过了8进制的范围,报此错误. shell脚本代码如下: #!/bin/bash a= ..} do a=$[$a+ ...

  5. Python中@修饰符的作用。

    '@'符号用作函数修饰符是python2.4新增加的功能,修饰符必须出现在函数定义前一行,不允许和函数定义在同一行.也就是说@A def f(): 是非法的. 只可以在模块或类定义层内对函数进行修饰, ...

  6. Effective C++ .08 别让异常逃离析构函数

    异常不怎么用,C++能自己控制析构过程,也就有这个要求了.容器不能完全析构其中的元素真是太危险了

  7. 爬虫之lxml - etree - xpath的使用

    # 解析原理: # - 获取页面源码数据 # - 实例化一个etree对象,并且将页面源码数据加载到该对象中 # - 调用该对象的xpath方法进行指定标签定位 # - xpath函数必须结合着xpa ...

  8. [ZOJ1015]:Fishing Net

    题面 Vjudge Sol 给出一个n个点的无向图,询问是否为弦图 做法见上上上篇博客 # include <bits/stdc++.h> # define RG register # d ...

  9. var a =10 与 a = 10的区别

    学习文章------汤姆大叔-变量对象 总结笔记 变量特点: ①变量声明可以存储在变量对象中.②变量不能直接用delete删除. var a =10 与 a = 10的区别: ①a = 10只是为全局 ...

  10. 原生js操作DOM基础-笔记

    原文参考http://mp.weixin.qq.com/s?__biz=MzU3MDA0NTMzMA==&mid=2247485490&idx=1&sn=15197b4b53e ...