C# 中关联数据库的两张表
在 C# 应用程序中,操作数据库是一项常见的任务,一个复杂的业务逻辑需要从多个表中获取和处理数据,为了实现这一点,可以使用 ADO.NET 或更高级的 ORM(对象关系映射)工具,如 Entity Framework,本文将介绍如何在 C# 中使用 ADO.NET 来关联两张表,并展示如何查询和处理这些数据。
1. 设置数据库和表结构
假设我们有一个名为School
的数据库,其中包含两张表:Students
和Courses
。Students
表存储学生的信息,而Courses
表存储课程的信息,每张表都有一个主键,并且通过外键进行关联。
列名 | 数据类型 | 说明 |
StudentID | int | 主键,自增 |
Name | nvarchar | 学生姓名 |
Age | int | 学生年龄 |
列名 | 数据类型 | 说明 |
CourseID | int | 主键,自增 |
CourseName | nvarchar | 课程名称 |
StudentID | int | 外键,引用 Students 表 |
2. 使用 ADO.NET 连接数据库
需要引入必要的命名空间:
using System; using System.Data; using System.Data.SqlClient;
可以创建一个方法来建立数据库连接:
public static SqlConnection GetConnection() { string connectionString = "Server=myServerAddress;Database=School;User Id=myUsername;Password=myPassword;"; return new SqlConnection(connectionString); }
3. 执行 SQL 查询以关联两张表
编写一个方法来执行 SQL 查询并获取关联的数据:
public static void GetStudentCourses() { using (SqlConnection conn = GetConnection()) { string query = @"SELECT Students.Name, Students.Age, Courses.CourseName FROM Students INNER JOIN Courses ON Students.StudentID = Courses.StudentID"; SqlCommand cmd = new SqlCommand(query, conn); conn.Open(); using (SqlDataReader reader = cmd.ExecuteReader()) { while (reader.Read()) { string studentName = reader["Name"].ToString(); int age = reader.IsDBNull("Age") ? 0 : reader.GetInt32("Age"); string courseName = reader["CourseName"].ToString(); Console.WriteLine($"Student: {studentName}, Age: {age}, Course: {courseName}"); } } } }
在上面的代码中,使用了INNER JOIN
来关联Students
和Courses
表,并通过SqlDataReader
读取结果集。
4. 使用 Entity Framework 关联两张表
如果使用 Entity Framework,可以通过以下步骤来实现相同的功能:
使用 NuGet 包管理器安装 Entity Framework:
Install-Package EntityFramework
定义与数据库表对应的实体类:
public class Student { public int StudentID { get; set; } public string Name { get; set; } public int Age { get; set; } public virtual ICollection<Course> Courses { get; set; } } public class Course { public int CourseID { get; set; } public string CourseName { get; set; } public int StudentID { get; set; } public virtual Student Student { get; set; } }
创建一个继承自DbContext
的类:
public class SchoolContext : DbContext { public DbSet<Student> Students { get; set; } public DbSet<Course> Courses { get; set; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.UseSqlServer("Server=myServerAddress;Database=School;User Id=myUsername;Password=myPassword;"); } }
使用 LINQ 查询来关联两张表:
public static void GetStudentCoursesEF() { using (SchoolContext context = new SchoolContext()) { var studentsWithCourses = context.Students.Include(s => s.Courses).ToList(); foreach (var student in studentsWithCourses) { Console.WriteLine($"Student: {student.Name}, Age: {student.Age}"); foreach (var course in student.Courses) { Console.WriteLine($"tCourse: {course.CourseName}"); } } } }
FAQs
Q1: 如果我想使用左连接而不是内连接,应该如何修改 SQL 查询?
A1: 你可以使用LEFT JOIN
来代替INNER JOIN
。
SELECT Students.Name, Students.Age, Courses.CourseName FROM Students LEFT JOIN Courses ON Students.StudentID = Courses.StudentID;
这样即使某些学生没有选修任何课程,他们也会出现在结果集中,未匹配的课程信息将为空。
Q2: 如果我希望在控制台输出中格式化输出,使其更具可读性,有什么建议吗?
A2: 你可以使用字符串插值和换行符来更好地格式化输出。
Console.WriteLine($"Student: {student.Name}, Age: {student.Age}"); if (student.Courses.Any()) { foreach (var course in student.Courses) { Console.WriteLine($"tCourse: {course.CourseName}"); } } else { Console.WriteLine("tNo courses enrolled."); }
这样可以确保每个学生的输出格式一致,并在没有选修课程时提供明确的提示。