Entity Framework知识点整理

Entity Framework

Entity Framework(EF)是微软提供的一种对象关系映射(Object-Relational Mapping,ORM)框架,用于在.NET应用程序和关系型数据库之间建立映射关系。它简化了数据访问层的开发,使开发人员可以将重点放在业务逻辑上,而无需过多关注数据库操作的细节。

Entity Framework 提供了一系列功能,包括:

  1. 数据库上下文(DbContext):用于管理数据库连接和对数据库进行操作的基本类。
  2. 实体类(Entity Class):用于表示数据库中的表或视图,每个实体类对应数据库中的一行数据。
  3. 查询语言:Entity Framework 提供了强大的查询语言(LINQ),允许开发人员使用面向对象的方式来查询数据库。
  4. 数据迁移(Data Migration):允许开发人员对数据库模式进行变更,并自动迁移现有数据以适应变更。
  5. 缓存:Entity Framework 可以缓存查询结果,提高数据检索性能。
  6. 遗留数据库支持:Entity Framework 支持将现有的数据库逆向工程为实体模型,从而可以利用EF来访问这些遗留数据库。

通过 Entity Framework,开发人员可以更快速、高效地进行数据库访问,减少了手动编写SQL语句的需求,并提供了更好的可维护性和可扩展性。无论是从零开始构建新的应用程序,还是与现有数据库进行集成,Entity Framework 都是一个强大而灵活的选择。

数据库上下文(DbContext)

例1 dbContext.Authors.ToListAsync();

ToListAsync() 是 Entity Framework 中的一个扩展方法,用于将查询结果转换为一个包含所有结果的 List 集合,并以异步的方式进行操作。

ToListAsync() 方法用于将查询结果转换为 List<T>,其中 T 是查询的元素类型。这个方法可以在查询的最后调用,以便将查询结果转换为一个具体的集合。

在你提供的代码示例中,ToListAsync() 用于将数据库上下文中的 Authors 表的所有记录取出并转换为一个包含所有记录的 List 集合,并以异步的方式进行操作。这样可以方便地对查询结果进行后续的处理或操作。

例2 dbContext.Books.Add(book);

dbContext.Books.Add(book); 是使用 Entity Framework 进行数据添加操作的代码示例。

在这个示例中,dbContext 是一个数据库上下文对象,而 Books 是数据库上下文中表示图书的集合或表。Add 方法用于向数据库上下文的 Books 集合中添加一个新的图书对象 book

添加操作的具体步骤如下:

  1. 实例化一个新的图书对象 book
  2. 调用 dbContext.Books.Add(book); 将新的图书对象添加到数据库上下文的 Books 集合中,但尚未写入数据库。
  3. 最后,你可以调用 dbContext.SaveChanges(); 保存更改,将新的图书对象写入数据库中。

具体操作可能还需要根据你的具体情况进行调整和额外的步骤,比如设置其他属性值、处理数据验证等。 Entity Framework 提供了一系列的方法和功能来帮助管理数据,并将更改写入数据库中。

例3 var count = await dbContext.SaveChangesAsync();

dbContext.SaveChangesAsync() 是 Entity Framework 中用于将所有对数据库作出的更改异步写入数据库中的方法。

在你提供的示例代码中,SaveChangesAsync() 被调用,并使用 await 进行异步等待,以便能够在处理其他操作之前等待保存更改的完成。

SaveChangesAsync() 方法返回一个表示异步操作的任务,该任务的值是一个整数,表示写入数据库的对象数、行数或状态的更改数。此处将这个值分配给了 count 变量。

通过使用异步编程模型来调用 SaveChangesAsync() 方法,可以避免阻塞主线程,从而提高应用程序的性能和效率。使用异步方式进行数据库操作通常比同步方式更具优势,因为在等待数据库操作完成的同时,线程可以自由地执行其他操作,从而提高并发处理能力和响应速度。

例4 .SingleOrDefaultAsync

.SingleOrDefaultAsync() 方法是 Entity Framework 中的异步方法,用于从数据库中检索一个单一的实体

在使用 .SingleOrDefaultAsync() 方法时,你需要在查询中设置适当的条件以确保只有一个实体符合条件。如果查询返回多个结果或没有结果,则会引发异常。

使用异步方式执行查询操作可以提高应用程序的性能和响应性,因为在等待查询完成的时间内,线程可以执行其他任务,使得整个应用程序在高负载或大量并发请求的情况下更高效地运行。

请注意,.SingleOrDefaultAsync() 方法将返回一个表示异步操作的任务,该任务的结果是检索到的单一实体。你可以使用 await 关键字等待异步操作完成,并使用变量接收结果。

示例代码:

var book = await dbContext.Books.SingleOrDefaultAsync(x => x.Id == bookId);

在上述示例中,我们使用 SingleOrDefaultAsync() 方法根据图书的唯一标识符进行查询,并将结果赋值给 book 变量。如果找到符合条件的图书,则返回一个实体;如果未找到或找到多个结果,则返回 null 或引发异常。

例5 .Include

.Include 方法用于在 Entity Framework 中预加载实体之间的关联数据

通过使用 .Include 方法,你可以指定要加载的关联属性,确保在获取实体数据时,对应的关联数据也会被加载到内存中。这样可以避免在后续操作中进行额外的数据库查询,提高性能和减少潜在的延迟。

.Include 方法接受一个 Lambda 表达式或字符串参数,用于指定要加载的关联属性。常见的用法是使用 Lambda 表达式,如 .Include(x => x.Category),其中 x 是实体类的导航属性,Category 是要加载的关联属性。你还可以在同一个查询中使用多个 .Include 调用来加载多个关联属性。

示例代码:

var books = await dbContext.Books.Include(x => x.Category).ToListAsync();

在上述示例中,我们使用 .Include(x => x.Category) 方法在查询图书时预加载了类别(Category)的关联数据。结果是返回一个包含图书集合及其关联类别数据的列表。

请注意,.Include 方法可以用于加载多层级的关联数据,例如 .Include(x => x.Category.Products) 可以同时加载图书的类别和该类别的产品。

预加载关联数据可以减少后续操作中的懒加载调用,从而提高性能,并减少潜在的 N+1 查询问题。然而,如果你预加载的关联数据过多,可能会导致性能下降或内存占用增加,因此需要根据实际情况进行权衡和优化。

例6  .State

.State 属性是 Entity Framework 中的一个枚举类型 EntityState 的成员,用于表示实体对象在上下文中的状态

通过设置实体对象的 .State 属性,你可以告诉 Entity Framework 如何处理该实体对象。常见的状态包括:

  • EntityState.Added 表示实体需要插入到数据库中
  • EntityState.Modified 表示实体需要更新到数据库中
  • EntityState.Deleted 表示实体需要从数据库中删除

此外,还有一些其他状态,例如 EntityState.Unchanged 表示实体没有被修改过,EntityState.Detached 表示实体没有被跟踪或已从上下文中分离。

示例代码:

var book = new Book { Title = "New Book", Author = "New Author" };
dbContext.Entry(book).State = EntityState.Added;
await dbContext.SaveChangesAsync();

在上述示例中,我们创建了一个新的 Book 对象并将其 .State 属性设置为 EntityState.Added,然后调用 SaveChangesAsync 方法将实体插入到数据库中。

请注意:在使用 .State 属性之前,应该首先调用上下文的.Set<T> 方法对实体对象进行跟踪。另外,在处理多个实体对象时,应该注意它们之间的关联关系,并按照正确的顺序设置它们的状态,以避免引发异常或导致数据一致性问题。

例7 var query = dbContext.Books as IQueryable<Book>;

var query = dbContext.Books as IQueryable<Book>; 是将 dbContext.Books 转换为 IQueryable<Book> 类型的查询变量

在 Entity Framework 中,查询可以通过 IQueryable<T> 接口来定义和构建。IQueryable<T> 接口表示一个可查询的数据源,并提供了一组可链式组合的查询操作,例如过滤、排序、投影等。通过构建 IQueryable<T> 查询,可以使用强类型的 LINQ 查询表达式来获取数据库中的数据。

在上述代码中,dbContext.Books 是从上下文中获取的 DbSet<Book> 对象,它表示数据库中 Book 对象的集合。然后,通过将其转换为 IQueryable<Book> 类型,并将结果存储在 query 变量中,我们可以使用 query 变量来以强类型的方式构建和执行查询操作。

示例代码:

var query = dbContext.Books as IQueryable<Book>;

// 使用 query 变量构建查询
var books = query.Where(x => x.Category == "Fiction")
                 .OrderBy(x => x.Title)
                 .ToList();

在上述示例中,我们使用 query 变量构建了一个查询,该查询首先筛选出类别为 “Fiction” 的图书,然后按照标题进行排序,并将结果保存在 books 变量中。

通过使用 IQueryable<T> ,可以将查询操作推迟到实际执行查询请求时,这意味着查询操作将在访问实际数据之前,等到需要结果时才会触发数据库的访问。这种延迟加载的机制可以有效地优化查询和提高性能。

查询语言(LINQ)

1 FirstOrDefault

FirstOrDefault 是一种 LINQ 方法,它在查询结果中返回满足指定条件的第一个元素,如果没有符合条件的元素,则返回默认值。它可以用于集合、数组、查询表达式等。

语法格式如下:

collection.FirstOrDefault(predicate)
  • collection:要查询的集合或数组。
  • predicate:一个用于定义筛选条件的委托表达式。

FirstOrDefault 在查询结果中查找满足条件的第一个元素。如果找到了符合条件的元素,则返回该元素;如果没有找到符合条件的元素,则返回元素类型的默认值(如果是引用类型,默认值为 null)。

需要注意的是,当调用 FirstOrDefault 时,查询结果可能为 null,因此在使用查询结果之前需要进行空引用检查。

2 .Where

.Where 是 Entity Framework 中的一个 LINQ 查询操作符,用于筛选符合指定条件的实体对象

通过使用 .Where 操作符,可以构建一个查询表达式,并将其作为参数传递给 IQueryable<T> 接口的实现,以过滤数据源中的元素。.Where 操作符需要一个 lambda 表达式作为参数,该表达式表示要应用于数据源中的每个元素的条件。

示例代码:

var query = dbContext.Books as IQueryable<Book>;

// 使用 Where 操作符筛选出类别为 "Fiction" 的图书
var books = query.Where(x => x.Category == "Fiction").ToList();

在上述示例中,query 是一个 IQueryable<Book> 类型的变量,它表示一个包含所有 Book 对象的数据源。然后,我们使用 .Where 操作符并传递一个 lambda 表达式来筛选出类别为 “Fiction” 的图书,并将结果保存在 books 变量中。

需要注意的是,.Where 操作符是一个延迟加载的操作符,也就是说,它只是构建了一个查询表达式,并没有立即执行查询。查询的实际执行将在你请求结果时发生,例如通过调用 ToListFirstFirstOrDefault 等操作符触发。这种延迟加载的机制可以有效地优化查询和提高性能。

除了 .Where 操作符之外,还有其他许多 LINQ 操作符可用于构建查询表达式,例如 .OrderBy.Skip.Take.Select 等等。通过组合多个操作符,可以构建出复杂的查询,并使用强类型的 LINQ 查询表达式来获取数据库中的数据。

3 .Contains

.Contains 是一个 LINQ 查询操作符,用于检查集合中是否包含指定的元素

在 Entity Framework 中,.Contains 操作符可以用于查询表达式中的 Where 子句,以筛选具有特定属性值的实体对象。

示例代码:

var query = dbContext.Books as IQueryable<Book>;

List<string> titles = new List<string> { "Book 1", "Book 2", "Book 3" };

// 使用 Contains 操作符查询标题在指定列表中的图书
var books = query.Where(x => titles.Contains(x.Title)).ToList();

在上述示例中,我们使用 titles 列表作为输入,并筛选出具有标题在该列表中的图书。使用 titles.Contains(x.Title) 表达式作为 .Where 操作符的参数,它将检查图书的标题属性是否在 titles 列表中。

需要注意的是,对于大型集合或查询的场景,.Contains 操作符可能会导致性能问题。在此情况下,可以考虑使用其他优化方式,如将集合转换为 HashSet,以提高查询的性能。

var query = dbContext.Books as IQueryable<Book>;

HashSet<string> titles = new HashSet<string> { "Book 1", "Book 2", "Book 3" };

// 使用 Contains 操作符查询标题在指定哈希集合中的图书
var books = query.Where(x => titles.Contains(x.Title)).ToList();

在上述优化的示例中,我们将 titles 列表转换为 HashSet<string>,使查询的性能更高效。HashSet 类型提供了更快的查找操作,因为它使用哈希表实现。

总结起来,.Contains 操作符在 LINQ 查询中常用于检查集合中是否包含指定元素,可以用于筛选实体对象的属性值与给定值列表中的值匹配的情况。

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值