查询和查找实体Querying and Finding Entities
本主题介绍使用实体框架查询数据的各种方法,包括 LINQ 和 Find 方法。 本主题所介绍的方法同样适用于查询使用 Code First 和 EF 设计器创建的模型。
使用查询查找实体Finding entities using a query
DbSet 和 IDbSet 可实现 IQueryable,因此可用作针对数据库编写 LINQ 查询的起点。 在此不适合深入讨论 LINQ,但以下提供了几个简单示例:
using (var context = new BloggingContext())
{
// Query for all blogs with names starting with B
var blogs = from b in context.Blogs
where b.Name.StartsWith("B")
select b;
// Query for the Blog named ADO.NET Blog
var blog = context.Blogs
.Where(b => b.Name == "ADO.NET Blog")
.FirstOrDefault();
}
请注意,DbSet 和 IDbSet 始终针对数据库创建查询,并且始终会涉及数据库往返,即使返回的实体已存在于上下文中。 出现以下情况时,会针对数据库执行查询:
- 查询由 foreach (C#) 或 For Each (Visual Basic) 语句枚举 。
- 查询由集合操作(如 ToArray、ToDictionary 或 ToList)枚举。
- 在查询最外部指定了 LINQ 运算符,例如 First 或 Any。
- 调用了以下方法:DbSet 上的 Load 扩展方法、DbEntityEntry.Reload 和 Database.ExecuteSqlCommand。
从数据库返回结果时,上下文中不存在的对象会附加到上下文。 如果某个对象已存在于上下文中,则不返回现有对象(不会使用数据库值覆盖该对象的属性在对应项中的当前值和原始值) 。
执行查询时,结果集中不回返回已添加到上下文但尚未保存到数据库的实体。 若要获取上下文中的数据,请参阅本地数据。
如果查询未从数据库返回任何行,则结果将是空集合,而不是 NULL 。
使用主键查找实体Finding entities using primary keys
DbSet 上的 Find 方法使用主键值来尝试查找由上下文跟踪的实体。 如果在上下文中未找到实体,则会向数据库发送查询以在其中查找实体。 如果未在上下文中或数据库中找到实体,则返回 NULL。
Find 与使用查询有两个重要区别:
- 只有未在上下文中找到具有给定键的实体时,才会往返数据库。
- Find 会返回处于“已添加”状态的实体。 即 Find 会返回已添加到上下文但尚未保存到数据库的实体。
通过主键查找实体Finding an entity by primary key
以下代码演示了 Find 的部分用法:
using (var context = new BloggingContext())
{
// Will hit the database
var blog = context.Blogs.Find(3);
// Will return the same instance without hitting the database
var blogAgain = context.Blogs.Find(3);
context.Blogs.Add(new Blog { Id = -1 });
// Will find the new blog even though it does not exist in the database
var newBlog = context.Blogs.Find(-1);
// Will find a User which has a string primary key
var user = context.Users.Find("johndoe1987");
}
通过组合主键查找实体Finding an entity by composite primary key
实体框架允许实体具有组合键,即由多个属性组成的键。 例如,用户可具有表示特定博客的用户设置的 BlogSettings 实体。 因为用户的每个博客只能拥有一个 BlogSettings,所以可以选择将 BlogId 和用户名结合作为 BlogSettings 的主键。 以下代码尝试查找 BlogId = 3,用户名 =“johndoe1987”的 BlogSettings:
using (var context = new BloggingContext())
{
var settings = context.BlogSettings.Find(3, "johndoe1987");
}
请注意,具有组合键时,需使用 ColumnAttribute 或 Fluent API 来指定组合键属性的顺序。 指定构成键的值时,对 Find 的调用必须使用此顺序。