在C# WinForms中实现数据库关联查询,需要结合ADO.NET组件与SQL语句进行多表数据联合操作。以下从基础到进阶的分步指南,涵盖主从表绑定、参数化查询和性能优化:
一、环境准备与数据建模
示例表结构:
sql
复制
CREATE TABLE Customers (
CustomerID INT PRIMARY KEY,
CustomerName NVARCHAR(50)
);
CREATE TABLE Orders (
OrderID INT PRIMARY KEY,
CustomerID INT,
OrderDate DATE,
FOREIGN KEY (CustomerID) REFERENCES Customers(CustomerID)
);
二、基础关联查询实现
步骤1:使用ADO.NET组件连接数据库
csharp
复制
using (SqlConnection conn = new SqlConnection("Your_Connection_String"))
{
string sql = @"
SELECT c.CustomerName, o.OrderID, o.OrderDate
FROM Customers c
INNER JOIN Orders o ON c.CustomerID = o.CustomerID";
SqlDataAdapter adapter = new SqlDataAdapter(sql, conn);
DataTable dt = new DataTable();
adapter.Fill(dt); // 填充DataTable
dataGridView1.DataSource = dt; // 绑定到DataGridView
}
三、主从表联动实现
场景:选择客户时显示对应订单
步骤1:加载客户列表到ComboBox
csharp
复制
using (SqlConnection conn = new SqlConnection(connectionString))
{
SqlDataAdapter adapter = new SqlDataAdapter("SELECT CustomerID, CustomerName FROM Customers", conn);
DataTable customers = new DataTable();
adapter.Fill(customers);
comboBox1.DisplayMember = "CustomerName";
comboBox1.ValueMember = "CustomerID";
comboBox1.DataSource = customers;
}
步骤2:根据选择加载订单
csharp
复制
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
if (comboBox1.SelectedValue == null) return;
int selectedCustomerID = (int)comboBox1.SelectedValue;
using (SqlConnection conn = new SqlConnection(connectionString))
{
string sql = @"
SELECT OrderID, OrderDate
FROM Orders
WHERE CustomerID = @CustomerID";
SqlCommand cmd = new SqlCommand(sql, conn);
cmd.Parameters.AddWithValue("@CustomerID", selectedCustomerID); // 参数化查询
SqlDataAdapter adapter = new SqlDataAdapter(cmd);
DataTable orders = new DataTable();
adapter.Fill(orders);
dataGridView1.DataSource = orders;
}
}
四、高级技巧:DataRelation实现关联
适用于数据集内关系维护:
csharp
复制
// 填充主表和子表
SqlDataAdapter customerAdapter = new SqlDataAdapter("SELECT * FROM Customers", conn);
SqlDataAdapter orderAdapter = new SqlDataAdapter("SELECT * FROM Orders", conn);
DataSet ds = new DataSet();
customerAdapter.Fill(ds, "Customers");
orderAdapter.Fill(ds, "Orders");
// 创建数据关系
DataRelation relation = new DataRelation(
"CustomerOrders",
ds.Tables["Customers"].Columns["CustomerID"],
ds.Tables["Orders"].Columns["CustomerID"]
);
ds.Relations.Add(relation);
// 绑定主表
dataGridView1.DataSource = ds.Tables["Customers"];
// 子表通过DataGridView关联显示
dataGridView2.DataSource = ds.Tables["Customers"];
dataGridView2.DataMember = "CustomerOrders";
五、性能优化策略
-
异步加载:
csharp
复制
private async Task LoadDataAsync() { using (SqlConnection conn = new SqlConnection(connectionString)) { await conn.OpenAsync(); SqlCommand cmd = new SqlCommand("SELECT * FROM Customers", conn); SqlDataReader reader = await cmd.ExecuteReaderAsync(); // 处理数据... } } -
索引优化:
sql
复制
CREATE INDEX IX_Orders_CustomerID ON Orders(CustomerID); -
分页查询:
sql
复制
SELECT * FROM ( SELECT ROW_NUMBER() OVER (ORDER BY OrderDate) AS RowNum, * FROM Orders ) AS MyOrders WHERE RowNum BETWEEN @StartIndex AND @EndIndex
六、安全与异常处理
-
参数化查询防御SQL注入:
csharp
复制
cmd.Parameters.Add("@CustomerID", SqlDbType.Int).Value = customerId; -
异常捕获:
csharp
复制
try { // 数据库操作... } catch (SqlException ex) { MessageBox.Show($"数据库错误:{ex.Message}"); } catch (Exception ex) { MessageBox.Show($"常规错误:{ex.Message}"); }
七、ORM方案对比(Entity Framework)
csharp
复制
var customerOrders = dbContext.Customers
.Include(c => c.Orders)
.Where(c => c.CustomerID == selectedId)
.ToList();
// 自动生成JOIN查询,简化数据操作
通过以上步骤,开发者可以在WinForms中高效实现多表关联查询,结合业务需求选择合适的数据加载策略,兼顾性能与安全性。




773

被折叠的 条评论
为什么被折叠?



