跳转到内容

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#调用存储过程是数据库编程的重要技能。通过本章学习,您应该掌握:

  • 基本存储过程调用方法
  • 参数传递和结果处理技术
  • 事务管理和错误处理
  • 性能优化和高级应用技巧

实践是掌握这些概念的关键,建议创建测试数据库并尝试各种调用场景。