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)的查询和加载模式。如果您有任何其他问题或需要进一步的指导,请随时告诉我。祝您编程愉快!

相关推荐
Yan-英杰10 分钟前
【python爬虫】利用代理IP爬取filckr网站数据
开发语言·人工智能·pytorch·python·机器学习·版本匹配
灏瀚星空12 分钟前
【爬虫学习】Python数据采集进阶:从请求优化到解析技术实战
爬虫·python·学习
欧先生^_^18 分钟前
ubuntu24.04与ubuntu22.04比,有什么新特性?
学习
每天题库21 分钟前
从法律层面剖析危化品证书:两证一证背后的安全逻辑
学习·安全·考试·题库·考证
软件开发技术深度爱好者39 分钟前
Python中的__init__和__new__方法解析
开发语言·python
笨手笨脚の1 小时前
【Bug】定时任务中 Jpa Save 方法失效
java·开发语言·bug·事务·jpa
coredx1 小时前
如何在 .NET 中构建一个好用的动态查询生成器
c#·.net·linq·ef core·表达式树
lanbing1 小时前
数据结构 -- 判断正误
java·开发语言·数据结构
٩( 'ω' )و2601 小时前
C++进阶--C++11(04)
开发语言·c++·c++11
豆沙沙包?1 小时前
2025年- H56-Lc164--200.岛屿数量(图论,深搜)--Java版
java·开发语言·图论