C Sharp 存储过程调用
外观
C#存储过程调用[编辑 | 编辑源代码]
介绍[编辑 | 编辑源代码]
存储过程(Stored Procedure)是预编译的SQL语句集合,存储在数据库中,可通过名称调用。在C#中调用存储过程可以提高性能、增强安全性并简化代码逻辑。本章将详细介绍如何在C#中调用SQL Server存储过程,包括参数传递、结果处理和实际应用场景。
存储过程基础[编辑 | 编辑源代码]
存储过程具有以下优势:
- 性能优化:预编译执行,减少网络传输
- 安全性:避免SQL注入攻击
- 代码复用:多个应用可共享同一过程
- 事务管理:可在过程中实现复杂事务
基本调用方法[编辑 | 编辑源代码]
以下是使用ADO.NET调用存储过程的基本步骤:
1. 创建SqlConnection连接数据库 2. 创建SqlCommand对象并指定为存储过程 3. 添加参数(如需) 4. 执行存储过程 5. 处理结果
代码示例[编辑 | 编辑源代码]
using System;
using System.Data;
using System.Data.SqlClient;
class Program
{
static void Main()
{
string connectionString = "Server=myServer;Database=myDB;Integrated Security=True;";
using (SqlConnection connection = new SqlConnection(connectionString))
{
try
{
connection.Open();
// 创建命令对象并指定为存储过程
using (SqlCommand command = new SqlCommand("usp_GetEmployeeDetails", connection))
{
command.CommandType = CommandType.StoredProcedure;
// 添加输入参数
command.Parameters.Add(new SqlParameter("@EmployeeID", 1001));
// 添加输出参数
SqlParameter outputParam = new SqlParameter("@Department", SqlDbType.NVarChar, 50);
outputParam.Direction = ParameterDirection.Output;
command.Parameters.Add(outputParam);
// 执行存储过程
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
Console.WriteLine($"Name: {reader["Name"]}, Position: {reader["Position"]}");
}
}
// 获取输出参数值
Console.WriteLine($"Department: {command.Parameters["@Department"].Value}");
}
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
}
}
}
输出示例:
Name: John Doe, Position: Developer Department: IT
参数类型详解[编辑 | 编辑源代码]
C#支持多种参数方向类型:
参数方向 | 描述 | 代码示例 |
---|---|---|
Input | 仅输入参数 | ParameterDirection.Input
|
Output | 仅输出参数 | ParameterDirection.Output
|
InputOutput | 双向参数 | ParameterDirection.InputOutput
|
ReturnValue | 返回值参数 | ParameterDirection.ReturnValue
|
返回值处理[编辑 | 编辑源代码]
存储过程可以通过RETURN语句返回值:
// 添加返回值参数
SqlParameter returnParam = new SqlParameter("@ReturnVal", SqlDbType.Int);
returnParam.Direction = ParameterDirection.ReturnValue;
command.Parameters.Add(returnParam);
// 执行后获取返回值
int result = (int)command.Parameters["@ReturnVal"].Value;
事务处理[编辑 | 编辑源代码]
存储过程调用可以包含在事务中:
using (SqlTransaction transaction = connection.BeginTransaction())
{
try
{
command.Transaction = transaction;
command.ExecuteNonQuery();
transaction.Commit();
}
catch
{
transaction.Rollback();
throw;
}
}
性能优化技巧[编辑 | 编辑源代码]
1. 使用CommandBehavior.SequentialAccess
处理大结果集
2. 对于频繁调用,考虑使用连接池
3. 使用异步方法ExecuteReaderAsync
提高响应性
实际案例[编辑 | 编辑源代码]
用户登录验证[编辑 | 编辑源代码]
创建存储过程:
CREATE PROCEDURE usp_ValidateLogin
@Username NVARCHAR(50),
@Password NVARCHAR(50),
@IsValid BIT OUTPUT
AS
BEGIN
IF EXISTS (SELECT 1 FROM Users WHERE Username = @Username AND Password = HASHBYTES('SHA2_256', @Password))
SET @IsValid = 1
ELSE
SET @IsValid = 0
END
C#调用代码:
bool ValidateUser(string username, string password)
{
using (SqlConnection connection = new SqlConnection(connectionString))
{
SqlCommand command = new SqlCommand("usp_ValidateLogin", connection);
command.CommandType = CommandType.StoredProcedure;
command.Parameters.AddWithValue("@Username", username);
command.Parameters.AddWithValue("@Password", password);
SqlParameter isValidParam = new SqlParameter("@IsValid", SqlDbType.Bit);
isValidParam.Direction = ParameterDirection.Output;
command.Parameters.Add(isValidParam);
connection.Open();
command.ExecuteNonQuery();
return (bool)isValidParam.Value;
}
}
常见问题[编辑 | 编辑源代码]
错误处理[编辑 | 编辑源代码]
- 始终检查参数是否为NULL
- 使用try-catch块处理SQL异常
- 记录错误详细信息
参数顺序[编辑 | 编辑源代码]
- 参数顺序应与存储过程定义一致
- 推荐使用命名参数而非依赖顺序
高级主题[编辑 | 编辑源代码]
表值参数[编辑 | 编辑源代码]
C#可以传递表值参数到存储过程:
DataTable dt = new DataTable();
// 填充DataTable...
SqlParameter tvpParam = command.Parameters.AddWithValue("@EmployeeList", dt);
tvpParam.SqlDbType = SqlDbType.Structured;
tvpParam.TypeName = "dbo.EmployeeTableType";
异步编程[编辑 | 编辑源代码]
使用async/await模式调用存储过程:
public async Task<List<Employee>> GetEmployeesAsync()
{
List<Employee> employees = new List<Employee>();
using (SqlConnection connection = new SqlConnection(connectionString))
{
await connection.OpenAsync();
using (SqlCommand command = new SqlCommand("usp_GetAllEmployees", connection))
{
command.CommandType = CommandType.StoredProcedure;
using (SqlDataReader reader = await command.ExecuteReaderAsync())
{
while (await reader.ReadAsync())
{
employees.Add(new Employee {
Id = reader.GetInt32(0),
Name = reader.GetString(1)
});
}
}
}
}
return employees;
}
总结[编辑 | 编辑源代码]
C#调用存储过程是数据库编程的重要技能。通过本章学习,您应该掌握:
- 基本存储过程调用方法
- 参数传递和结果处理技术
- 事务管理和错误处理
- 性能优化和高级应用技巧
实践是掌握这些概念的关键,建议创建测试数据库并尝试各种调用场景。