在C#开发中,当业务需要同时获取多张关联表的数据时,就需要用到数据库的跨表查询,而JOIN操作是实现跨表查询的核心方式。通过JOIN可以将两张或多张表按照关联字段拼接,一次性返回所需的关联数据,避免多次单表查询后再手动关联的低效操作。

数据库JOIN操作的基本类型
常见的JOIN类型有四种,不同的JOIN对应不同的数据返回规则:
- INNER JOIN(内连接):只返回两张表中关联字段匹配的行,不匹配的数据不会出现在结果中。
- LEFT JOIN(左连接):返回左表的所有行,以及右表中关联字段匹配的行,右表没有匹配的行则对应字段为NULL。
- RIGHT JOIN(右连接):返回右表的所有行,以及左表中关联字段匹配的行,左表没有匹配的行则对应字段为NULL。
- FULL JOIN(全连接):返回左右两张表的所有行,任意一边没有匹配的行则对应字段为NULL。
C#中实现跨表查询的步骤
C#通过ADO.NET组件可以执行带JOIN的SQL语句,完成跨表查询,整体流程分为四步:
1. 建立数据库连接
首先需要引入System.Data.SqlClient命名空间,配置数据库连接字符串,创建SqlConnection对象并打开连接。
using System.Data.SqlClient; // 数据库连接字符串,根据实际数据库配置修改 string connStr = "Server=127.0.0.1;Database=TestDB;User Id=sa;Password=123456;"; SqlConnection conn = new SqlConnection(connStr); conn.Open();
2. 编写带JOIN的SQL语句
根据需要的JOIN类型,编写对应的SQL查询语句,明确关联表和关联字段。假设我们有两张表,用户表Users(字段:Id, UserName, Age)和订单表Orders(字段:OrderId, UserId, OrderPrice),需要查询每个用户对应的订单信息,使用INNER JOIN关联两张表的UserId字段。
-- 内连接查询用户和对应的订单 SELECT u.Id, u.UserName, u.Age, o.OrderId, o.OrderPrice FROM Users u INNER JOIN Orders o ON u.Id = o.UserId;
3. 执行查询并读取结果
创建SqlCommand对象传入SQL语句和连接对象,再通过SqlDataReader读取查询结果,将数据处理为需要的格式。
// 创建命令对象,传入带JOIN的SQL语句和连接
string sql = "SELECT u.Id, u.UserName, u.Age, o.OrderId, o.OrderPrice FROM Users u INNER JOIN Orders o ON u.Id = o.UserId;";
SqlCommand cmd = new SqlCommand(sql, conn);
// 执行查询,获取读取器
SqlDataReader reader = cmd.ExecuteReader();
// 循环读取结果
while (reader.Read())
{
int userId = reader.GetInt32(0);
string userName = reader.GetString(1);
int userAge = reader.GetInt32(2);
int orderId = reader.GetInt32(3);
decimal orderPrice = reader.GetDecimal(4);
Console.WriteLine($"用户ID:{userId},用户名:{userName},年龄:{userAge},订单ID:{orderId},订单金额:{orderPrice}");
}
// 关闭读取器和连接
reader.Close();
conn.Close();
4. 不同JOIN类型的C#实现示例
如果需要查询所有用户,即使没有订单也返回用户信息,只需要把INNER JOIN换成LEFT JOIN即可,代码其他部分不需要修改:
// 左连接查询所有用户及对应的订单,无订单的用户订单字段为NULL
string leftJoinSql = "SELECT u.Id, u.UserName, u.Age, o.OrderId, o.OrderPrice FROM Users u LEFT JOIN Orders o ON u.Id = o.UserId;";
SqlCommand leftCmd = new SqlCommand(leftJoinSql, conn);
SqlDataReader leftReader = leftCmd.ExecuteReader();
while (leftReader.Read())
{
int userId = leftReader.GetInt32(0);
string userName = leftReader.GetString(1);
int userAge = leftReader.GetInt32(2);
// 判断订单ID是否为空,为空则显示无订单
string orderInfo = leftReader.IsDBNull(3) ? "无订单" : $"订单ID:{leftReader.GetInt32(3)},金额:{leftReader.GetDecimal(4)}";
Console.WriteLine($"用户ID:{userId},用户名:{userName},年龄:{userAge},{orderInfo}");
}
leftReader.Close();
注意事项
执行跨表查询时需要注意几个问题:一是SQL语句中的表名和字段名要和数据库实际结构一致,避免语法错误;二是读取数据时要注意字段是否为空,尤其是LEFT JOIN、RIGHT JOIN场景下,不匹配的字段会返回NULL,需要用IsDBNull方法判断后再处理;三是查询完成后要及时关闭SqlDataReader和SqlConnection,避免占用数据库连接资源。如果需要频繁执行跨表查询,也可以将查询逻辑封装为方法,提高代码复用性。