C#使用Entity Framework Core处理数据库(二)

Entity Framework Core(EF Core)是一个轻量级、跨平台的对象关系映射(ORM)框架,用于在.NET应用程序中处理数据库操作。它提供了一种将数据库中的数据映射到.NET对象模型的方法,使开发人员可以使用面向对象的方式进行数据库操作,而无需直接编写SQL语句。

上一篇文章讲了如何在C#中构建EF Core模型:C#使用Entity Framework Core处理数据库(一)

1.查询EF Core模型

在上一篇文章中我们编辑了一个名为"Product"的实体,它具有"id"、"Name"和"Price"属性

csharp 复制代码
public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    public decimal Price { get; set; }
}

现在编写一些简单的LINQ查询代码用于从数据库中检索所有产品的名称和价格

csharp 复制代码
using (var context = new YourEfCoreContext())
{
    var products = context.Products
        .Select(p => new { p.Name, p.Price })
        .ToList();
}

过滤结构中返回的实体

"Filtered include"是Entity Framework Core中的一种技术,允许您在加载相关实体时应用过滤条件。这使您能够对关联实体进行过滤,并仅加载符合特定条件的相关数据,而不是加载全部数据。

在EF Core中,通过使用Where和Include方法结合来实现filtered include。这样可以在检索相关实体时应用筛选条件,以减少检索到的数据量并且只获取符合条件的相关数据。

如果您想要在LINQ查询中进行过滤,并包含特定的实体,您可以使用Where来过滤结果,然后使用Include来包含另一个实体。以下是一个示例代码:

csharp 复制代码
using (var context = new YourEfCoreContext())
{
    var productsWithCategory = context.Products
        .Where(p => p.Price > 50) // 过滤价格大于50的产品
        .Include(p => p.Category) // 包含关联的Category实体
        .ToList();
}

获取生成的SQL

EF Core5.0提供了一种简单快捷的方法来查看生成的SQL

还是上面的例子:

csharp 复制代码
 using (var context = new YourEfCoreContext())
        {
            var query = context.Products
                .Where(p => p.Price > 50)
                .Include(p => p.Category);

            var sql = query.ToQueryString();
            Console.WriteLine(sql);
        }

生成的 SQL 查询语句将是以下内容:
SELECT "p"."Id", "p"."Name", "p"."Price", "p"."CategoryId", "c"."Id", "c"."Name"FROM "Products" AS "p" LEFT JOIN "Categories" AS "c" ON "p"."CategoryId" = "c"."Id" WHERE "p"."Price" > 50

定义全局过滤器

在 Entity Framework Core 中,您可以使用全局查询过滤器来自动应用于所有对数据库上下文执行的查询。这在需要对数据进行软删除或者多租户隔离的情况下特别有用。

csharp 复制代码
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder);

    // 添加全局过滤器
    modelBuilder.Entity<Product>().HasQueryFilter(p => !p.IsDeleted);
}

2.使用EF Core加载模式

立刻加载实体

在 Entity Framework Core 中,可以使用 Include 或 ThenInclude 方法来立即加载相关实体。立即加载可以避免延迟加载带来的性能问题,确保在查询时将相关实体一起加载到内存中。

csharp 复制代码
using (var context = new YourEfCoreContext())
{
    var product = context.Products
        .Include(p => p.Category)
        .FirstOrDefault(p => p.Id == productId);
}

在上面的示例中,通过调用 Include(p => p.Category) 方法,我们告诉 EF Core 在检索产品时立即加载与之关联的类别实体。这样,在查询结果返回时,产品及其对应的类别会一并加载到内存中。

请注意,过度使用立即加载可能导致性能问题,因为它会在单个查询中检索大量相关数据。在实际应用中,请根据需要谨慎使用立即加载。

启用延迟加载

在 Entity Framework Core 中,默认情况下是不支持延迟加载的。不过,您可以通过安装 Microsoft.EntityFrameworkCore.Proxies 包并启用 UseLazyLoadingProxies 方法来启用延迟加载功能。以下是一个示例:

  1. 首先,安装 Microsoft.EntityFrameworkCore.Proxies 包:
bash 复制代码
Install-Package Microsoft.EntityFrameworkCore.Proxies
  1. 然后,在创建数据库上下文的地方启用延迟加载:
csharp 复制代码
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    base.OnConfiguring(optionsBuilder);
    optionsBuilder.UseLazyLoadingProxies();
}
  1. 启用了延迟加载后,当您访问导航属性时,相关的实体将会在需要时自动从数据库中加载。例如:
csharp 复制代码
using (var context = new YourEfCoreContext())
{
    var product = context.Products.FirstOrDefault(p => p.Id == productId);
    
    // 延迟加载类别实体
    var category = product.Category;
}

在这个示例中,当访问 product.Category 时,如果该属性还没有被加载,EF Core 将会立即从数据库中检索相关的类别实体。

请注意,尽管延迟加载提供了便利,但它也可能导致性能问题,并且容易引起 N+1 查询问题。因此,在使用延迟加载时要格外小心。

显示加载实体

另一种加载模式是显示加载,这通常用于在已经获取了一个实体之后,需要加载其相关实体的情况。显式加载允许您在需要时精确控制哪些相关实体被加载,从而避免了不必要的数据加载和性能问题。以下是一个示例:

csharp 复制代码
using (var context = new YourEfCoreContext())
{
    var product = context.Products.FirstOrDefault(p => p.Id == productId);

    // 显示加载类别实体
    context.Entry(product)
        .Reference(p => p.Category)
        .Load();
}

在上面的示例中,我们首先获取了一个产品实体,然后使用 context.Entry(product).Reference(p => p.Category).Load() 来显式加载该产品对应的类别实体。这样可以确保在需要时加载相关实体,而不是默认情况下自动加载。

感谢您阅读本文中关于Entity Framework Core的示例代码和说明。希望这些示例能够帮助您更好地理解在C#中Entity Framework Core(EF Core)的查询和加载模式。如果您有任何其他问题或需要进一步的指导,请随时告诉我。祝您编程愉快!

相关推荐
魔道不误砍柴功1 分钟前
Java 中如何巧妙应用 Function 让方法复用性更强
java·开发语言·python
Nu11PointerException3 分钟前
JAVA笔记 | ResponseBodyEmitter等异步流式接口快速学习
笔记·学习
闲晨4 分钟前
C++ 继承:代码传承的魔法棒,开启奇幻编程之旅
java·c语言·开发语言·c++·经验分享
老猿讲编程31 分钟前
一个例子来说明Ada语言的实时性支持
开发语言·ada
Chrikk1 小时前
Go-性能调优实战案例
开发语言·后端·golang
幼儿园老大*2 小时前
Go的环境搭建以及GoLand安装教程
开发语言·经验分享·后端·golang·go
canyuemanyue2 小时前
go语言连续监控事件并回调处理
开发语言·后端·golang
杜杜的man2 小时前
【go从零单排】go语言中的指针
开发语言·后端·golang
萧鼎3 小时前
Python并发编程库:Asyncio的异步编程实战
开发语言·数据库·python·异步
学地理的小胖砸3 小时前
【一些关于Python的信息和帮助】
开发语言·python