如何使用Entity Framework查询Mysql数据库 并实现多表联查

本文介绍了EntityFrameworkCore(EFCore)的关键特性和使用场景,包括其跨平台的特性、多数据库支持、简化数据访问以及在.NET中通过ORM进行多表联查的示例。开发者可以学习如何通过NuGet包安装和配置EFCore,以及如何在项目中创建上下文类和实体类进行数据库操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

🍀简介

Entity Framework Core (EF Core) 是一种轻量级、可扩展、开源且跨平台的对象关系映射(O/RM)框架,专为 .NET 平台设计。以下是 EF Core 的一些关键特点:

  1. 多数据库支持:EF Core 支持多种数据库引擎,包括 SQL Server、MySQL、PostgreSQL、SQLite 等,使得开发者可以根据项目需求选择合适的数据库系统。
  2. 简化数据访问:它允许 .NET 开发者使用 .NET 对象来处理数据库数据,大多数情况下无需编写传统的数据访问代码(如 SQL 或其他查询语句),从而简化了数据访问层的开发工作。
  3. 模型、查询与数据保存:EF Core 提供了创建数据模型、执行查询和保存数据的功能。开发者可以通过定义 .NET 类和属性来构建数据模型,然后使用 LINQ(语言集成查询)来查询数据,以及通过 SaveChanges 方法来保存对数据的更改。
  4. 易于安装和使用:EF Core 可以通过 NuGet 包轻松安装和更新。开发者需要在项目中安装 Microsoft.EntityFrameworkCore 包以及相应的数据库提供程序包,即可开始使用 EF Core。

🍀演示

在下面案例中我们通过依赖注入的方式,使用ORM工具Entity Framework查询Mysql数据库中的数据,并实现多表联查

假设我们有一个user用户表,其中occupationid对应的就是下面职业表中的id

 职业表Occupations

 

 现在我们需要查出用户的职业是什么,在MySQL中我们可以通过LEFT JOIN实现多表查询。如下sql语句。

SELECT name,opname FROM Users 
LEFT JOIN Occupations ON Users.opid = Occupations.id

 如果想要在EFCore中完成这种需求应该怎么操作呢。

🍀安装nuget包

分别安装如下两个nuget包,具体版本要参考自己实际的MySQL版本

NuGet\Install-Package Microsoft.Extensions.Hosting -Version 8.0.0
NuGet\Install-Package Pomelo.EntityFrameworkCore.MySql -Version 7.0.0

🍀创建上下文类

首先创建一个继承自 DbContext 的上下文类,使用DbSet 属性来表示数据库中的表

public class MyContext : DbContext
{
    public MyContext(DbContextOptions<MyContext> options)
        : base(options)
    {
    }

    public virtual DbSet<User> Users { get; set; } = null!;
    
    public virtual DbSet<Occupation> Occupations { get; set; } = null!;
}

然后分别创建我们数据库两张表的实体类,它们通过导航属性 occupationid 相互关联

public class User
{
    public int Id { get; set; }
    public string Name { get; set; }
    
    public int occupationid { get; set; }
    
    public Occupation Occupation { get; set; }
}

public class Occupation
{
    public int Id { get; set; }
    
    public string opname { get; set; }
}

🍀依赖注入

打开我们的program类,创建一个主机构建器,通过AddDbContextPool注册 MyContext 类型到服务容器中。

然后通过AddHostedService 方法添加一个后台服务,该服务将在应用程序启动时运行,这里我添加的是selectUser服务,也就是项目启动的时候会执行它,接下来我们去写selectUser服务

class Program
{
    public static void Main(string[] args)
    {
         // 创建一个主机构建器,用于配置应用程序的启动和依赖注入。
        HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);

        // 配置服务,这里添加了数据库上下文池,用于管理数据库连接。
        builder.Services.AddDbContextPool<MyContext>(
            p =>
            {
                p.UseMySql("server=127.0.0.1;uid=root;pwd=password;database=mydb", new MySqlServerVersion("5.7"),
                    opt => opt.UseQuerySplittingBehavior(QuerySplittingBehavior.SplitQuery));
                p.LogTo(Console.WriteLine, LogLevel.Information);
                p.EnableSensitiveDataLogging(true);
            }, 150);

        // 添加宿主服务,我们稍后创建selectUser服务
        builder.Services.AddHostedService<selectUser>();

         // 构建宿主。
        using IHost host = builder.Build();

        // 运行宿主,启动应用程序。
        host.Run();
    }
}

定义一个名为selectUser的类,继承自BackgroundService ,在构造函数中添加参数MyContext ,项目运行时会通过依赖注入给当前类提供一个MyContext上下文,这样,selectUser 类就可以使用这个 DbContext 实例来访问数据库。

使用 _myContext.Users 来访问数据库中的 Users 表。Include(p => p.Occupation) 表示在查询用户时,还要包括关联的 Occupation 实体

public class selectUser : BackgroundService
{
    private readonly MyContext _myContext;

    public selectUser(MyContext myContext)
    {
        _myContext = myContext;
    }
    

    protected override async Task<int> ExecuteAsync(CancellationToken stoppingToken)
    {
        var find = _myContext.Users
            .Include(p => p.Occupation)
            .ToList();
        foreach (var user in find)
        {
            Console.WriteLine(user.Name);
        }

        return 0;
    }
}

这样在程序执行的时候,我们就可以通过多表联查获得用户的职业

### Spring Boot 中实现多表关联操作 在 Spring Boot 应用程序中,可以通过多种方式实现多表关联查询。以下是基于 JPA 和 MyBatis 的两种常见方法。 #### 方法一:使用 Spring Data JPA 实现多表联查 通过 `@EntityGraph` 或者原生 SQL 查询的方式可以在不修改实体类的情况下完成多表联合查询。下面是一个具体的例子: ##### 配置依赖 确保项目的 `pom.xml` 文件中有以下依赖项: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <scope>runtime</scope> </dependency> ``` ##### 定义实体类 假设我们有两个表:`User` 和 `Order`,它们之间是一对多的关系。 ```java @Entity public class User { @Id private Long id; private String name; @OneToMany(mappedBy = "user", fetch = FetchType.LAZY) private List<Order> orders; // 用户拥有的订单列表 // Getter and Setter methods... } @Entity public class Order { @Id private Long orderId; private Double amount; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "userId") private User user; // 订单所属的用户 // Getter and Setter methods... } ``` ##### 自定义 Repository 接口 创建一个自定义接口来执行复杂的查询逻辑。 ```java public interface UserRepository extends JpaRepository<User, Long> { @Query(value = "SELECT u.id AS userId, u.name AS userName, o.orderId, o.amount FROM User u LEFT JOIN u.orders o WHERE u.id = :id", nativeQuery = true) List<Object[]> findUserWithOrders(@Param("id") Long id); } ``` 上述代码实现了从 `User` 表及其关联的 `Order` 表中提取数据的功能[^1]。 #### 方法二:使用 MyBatis 实现多表联查 MyBatis 提供了一种灵活的方式来处理复杂查询场景,尤其是当涉及到多个表之间的关系时。 ##### 添加 MyBatis 依赖 同样,在 `pom.xml` 文件中加入如下内容: ```xml <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.4.0</version> </dependency> ``` ##### 创建 Mapper 接口 编写一个 Mapper 来描述所需的 SQL 查询语句。 ```java @Mapper public interface UserMapper { @Select("SELECT u.*, GROUP_CONCAT(o.order_id) as order_ids FROM users u LEFT JOIN orders o ON u.id = o.user_id WHERE u.id=#{id} GROUP BY u.id") Map<String, Object> getUserAndOrders(Long id); } ``` 这里利用了 MySQL 的聚合函数 `GROUP_CONCAT()` 将用户的订单 ID 列表拼接成字符串返回给调用方[^4]。 #### 总结比较 | 特性 | JPA | MyBatis | |-----------------|---------------------------------------|--------------------------------------| | 易于维护 | 更加面向对象 | 能够更好地控制底层SQL | | 学习曲线 | 较陡 | 平缓 | | 执行效率 | 可能因懒加载机制而变慢 | 直接操控SQL通常更快 | 如果团队成员熟悉 Hibernate/JPA 技术栈,则推荐优先考虑前者;反之则后者可能更适合那些希望完全掌控数据库交互细节的人群。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱吃香蕉的阿豪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值