关于System.Data.ParameterDirection四个枚举类型所起的作用

本文详细解析了.NET中SQL参数的不同方向类型(输入、输出、输入输出及返回值),并通过具体实例展示了这些参数如何与数据库存储过程交互。

因为做应用系统肯定要和数据库打交道 而我最常接触的就是SQL 2000数据库 常规的方式就是写存储过程类然后和数据库的存储过程进行交互 执行命令或者取得数据 

相信大家都知道.net中有四个关于参数传入传出的类型 分别是:

System.Data.ParameterDirection.Input

System.Data.ParameterDirection.InputOutput

System.Data.ParameterDirection.Output

System.Data.ParameterDirection.ReturnValue

感官上理解就是只能传入 即可以传入又可以传出 只能传出 返回值 实际应用中和感官的理解一致吗?我也不大清楚 反正以前做的系统都没有遇见问题 所以也没有把这几个参数搞的很明白 不过心中始终有疑问 所以今天就抽了点时间做了一个例子把原理搞清楚

首先我把.Net中的参数定义为形式参数 而把存储过程的参数定义为实际参数

比如:cmd.Parameters.Add("@Input", System.Data.SqlDbType.Int);  @Input为形式参数

而存储过程的@Input int,  @Input为实际参数

 

得到的结论如下:

数据库存储过程的实际参数如果没有默认值则形式参数必须传值给实际参数

但是如果形式参数的类型为ParameterDirection.Output 则传给实际参数的永远是空值

如果形式参数的类型为ParameterDirection.ReturnValue 则形式参数不会传值给实际参数 实际参数必须有默认值  否则代码会报错

如果形式参数类型为ParameterDirection.InputOutput 或者 ParameterDirection.Output 则实际参数必须有output 关键字

 

另外需要注意的是在.net System.DBNull.Value表示数据库参数为空值 而不是null

 

 

用于测试的存储过程如下:

/*

     function:测试C# ParameterDirection 枚举类的作用

     coder:benniuniu

     time:2007-11-25

*/

CREATE PROCEDURE proc_test_SQLParametersValue

@Input int,

@InputOutput int output,

@Output int output,

@ReturnValue int=1

AS  

     select @Input as Input,@InputOutput as InputOutput,@Output as [Output],@ReturnValue as ReturnValue

     return 2

GO

 

测试用的C# 代码类如下:

using System;

using System.Collections.Generic;

using System.Text;

using System.Data.SqlClient;

using System.Configuration;

using System.Data;

 

namespace CoderHelper.Test

{

    class SQLParametersValue

    {

        public SQLParametersValue()

        {

 

        }

 

        public int? Input=1;

        public int? InputOutput=2;

        public int? Output=3;

        public int? ReturnValue=4;

 

        public int? Input2;

        public int? InputOutput2;

        public int? Output2;

        public int? ReturnValue2;

 

        public void GetData(DataTable dt)

        {

            SqlConnection conn = new SqlConnection(ConfigurationSettings.AppSettings["LocalSqlConnectionString"]);

            SqlCommand cmd = new SqlCommand();

            cmd.Connection = conn;

            cmd.CommandType = System.Data.CommandType.StoredProcedure;

            cmd.CommandText = "proc_test_SQLParametersValue";

 

            cmd.Parameters.Add("@Input", System.Data.SqlDbType.Int);

            cmd.Parameters["@Input"].Direction = System.Data.ParameterDirection.Input;

            if (Input == null)

            {

                cmd.Parameters["@Input"].Value = System.DBNull.Value;

            }

            else

            {

                cmd.Parameters["@Input"].Value = Input;

            }           

 

            cmd.Parameters.Add("@InputOutput", System.Data.SqlDbType.Int);

            cmd.Parameters["@InputOutput"].Direction = System.Data.ParameterDirection.InputOutput;

            if (InputOutput == null)

            {

                cmd.Parameters["@InputOutput"].Value = System.DBNull.Value;

            }

            else

            {

                cmd.Parameters["@InputOutput"].Value = InputOutput;

            }

 

            cmd.Parameters.Add("@Output", System.Data.SqlDbType.Int);

            cmd.Parameters["@Output"].Direction = System.Data.ParameterDirection.Output;

            if (Output == null)

            {

                cmd.Parameters["@Output"].Value = System.DBNull.Value;

            }

            else

            {

                cmd.Parameters["@Output"].Value = Output;

            }

 

            cmd.Parameters.Add("@ReturnValue", System.Data.SqlDbType.Int);

            cmd.Parameters["@ReturnValue"].Direction = System.Data.ParameterDirection.ReturnValue;

            if (ReturnValue == null)

            {

                cmd.Parameters["@ReturnValue"].Value = System.DBNull.Value;

            }

            else

            {

                cmd.Parameters["@ReturnValue"].Value = ReturnValue;

            }

 

            SqlDataAdapter sa = new SqlDataAdapter(cmd);

            try

            {

                if (conn.State == System.Data.ConnectionState.Closed)

                {

                    conn.Open();

                }

 

                sa.Fill(dt);

 

                if (cmd.Parameters["@Input"].Value != System.DBNull.Value)

                    Input2 = Convert.ToInt32(cmd.Parameters["@Input"].Value);

 

                if (cmd.Parameters["@InputOutput"].Value != System.DBNull.Value)

                    InputOutput2 = Convert.ToInt32(cmd.Parameters["@InputOutput"].Value);

 

                if (cmd.Parameters["@Output"].Value != System.DBNull.Value)

                    Output2 = Convert.ToInt32(cmd.Parameters["@Output"].Value);

 

                if (cmd.Parameters["@ReturnValue"].Value != System.DBNull.Value)

                    ReturnValue2 = Convert.ToInt32(cmd.Parameters["@ReturnValue"].Value);

 

            }

            catch (Exception ex)

            {

 

            }

            finally

            {

                conn.Close();

            }

 

           

        }

 

    }

}

 

如上代码

public int? Output=3; 但是实际传给存储过程的值还是空值

public int? ReturnValue=4; 但是实际没有传值给存储过程

ReturnValue2 = Convert.ToInt32(cmd.Parameters["@ReturnValue"].Value); 取的是存储过程return的返回值此例存储过程代码是 return 2 所以取得值是2

 

using System; using System.Collections.Generic; using System.Configuration; using System.Data; using System.Data.Common; using System.Data.SqlClient; using System.Linq; using Oracle.ManagedDataAccess.Client; using MySql.Data.MySqlClient; namespace StorehouseServer.Helper { /// <summary> /// 数据库Helper /// </summary> public class DatabaseHelper : IDisposable { private DbConnection _connection; private readonly DatabaseType _databaseType; private string _connectionString; private const int MaxRetryCount = 3; private const int RetryDelayMs = 1000; public enum DatabaseType { SqlServer, Oracle, MySql } /// <summary> /// 构造函数 /// </summary> /// <param name="databaseType">数据库类型</param> /// <param name="connectionStringName">配置文件中连接字符串的名称</param> /// <exception cref="ArgumentNullException">当connectionStringName为null或空时抛出</exception> /// <exception cref="ConfigurationErrorsException">当连接字符串配置不存在时抛出</exception> public DatabaseHelper(DatabaseType databaseType, string connectionStringName) { if (string.IsNullOrWhiteSpace(connectionStringName)) throw new ArgumentNullException(nameof(connectionStringName), "Connection string name cannot be null or empty."); _databaseType = databaseType; var connectionSettings = ConfigurationManager.ConnectionStrings[connectionStringName]; if (connectionSettings == null) throw new ConfigurationErrorsException($"Connection string '{connectionStringName}' not found in configuration."); // 从配置文件中获取加密的连接字符串并解密 var encryptedConnString = connectionSettings.ConnectionString; if (string.IsNullOrWhiteSpace(encryptedConnString)) throw new ConfigurationErrorsException($"Connection string '{connectionStringName}' is empty."); _connectionString = StringEncryptor.Decrypt(encryptedConnString); // 确保连接字符串包含连接池设置 EnsureConnectionPoolSettings(); } /// <summary> /// 确保连接字符串包含连接池设置 /// </summary> private void EnsureConnectionPoolSettings() { // 根据不同数据库类型添加连接池优化参数 switch (_databaseType) { case DatabaseType.SqlServer: var sqlBuilder = new SqlConnectionStringBuilder(_connectionString) { Pooling = true, MaxPoolSize = 100, MinPoolSize = 5, ConnectTimeout = 15 }; _connectionString = sqlBuilder.ToString(); break; case DatabaseType.Oracle: var oracleBuilder = new OracleConnectionStringBuilder(_connectionString) { Pooling = true, MaxPoolSize = 100, MinPoolSize = 5, ConnectionTimeout = 15 }; _connectionString = oracleBuilder.ToString(); break; case DatabaseType.MySql: var mysqlBuilder = new MySqlConnectionStringBuilder(_connectionString) { Pooling = true, MaximumPoolSize = 100, MinimumPoolSize = 5, ConnectionTimeout = 15 }; _connectionString = mysqlBuilder.ToString(); break; } } /// <summary> /// 初始化数据库连接 /// </summary> private DbConnection InitializeConnection() { DbConnection connection; switch (_databaseType) { case DatabaseType.SqlServer: connection = new SqlConnection(_connectionString); break; case DatabaseType.Oracle: connection = new OracleConnection(_connectionString); break; case DatabaseType.MySql: connection = new MySqlConnection(_connectionString); break; default: throw new ArgumentException("Unsupported database type"); } // 设置连接超时和重试策略 connection.ConnectionString = _connectionString; return connection; } /// <summary> /// 获取数据库连接(带重试机制) /// </summary> public DbConnection GetConnection() { if (_connection == null) { _connection = InitializeConnection(); } // 检查连接状态,必要时重新连接 if (_connection.State != ConnectionState.Open) { int retryCount = 0; while (retryCount < MaxRetryCount) { try { _connection.Open(); return _connection; } catch (DbException) { retryCount++; if (retryCount >= MaxRetryCount) throw; System.Threading.Thread.Sleep(RetryDelayMs); // 尝试重新初始化连接 try { _connection.Dispose(); } catch { } _connection = InitializeConnection(); } } } return _connection; } /// <summary> /// 创建新的数据库连接(不自动打开) /// </summary> public DbConnection CreateConnection() { DbConnection connection; switch (_databaseType) { case DatabaseType.SqlServer: connection = new SqlConnection(_connectionString); break; case DatabaseType.Oracle: connection = new OracleConnection(_connectionString); break; case DatabaseType.MySql: connection = new MySqlConnection(_connectionString); break; default: throw new ArgumentException("Unsupported database type"); } return connection; } /// <summary> /// 执行非查询SQL语句 /// </summary> /// <param name="sql">SQL语句</param> /// <param name="parameters">参数</param> /// <returns>受影响的行数</returns> /// <exception cref="ArgumentNullException">当sql为null或空时抛出</exception> public int ExecuteNonQuery(string sql, params DbParameter[] parameters) { if (string.IsNullOrWhiteSpace(sql)) throw new ArgumentNullException(nameof(sql), "SQL statement cannot be null or empty."); using (var connection = GetConnection()) { using (DbCommand command = CreateCommand(connection, sql, parameters)) { return command.ExecuteNonQuery(); } } } /// <summary> /// 执行查询并返回DataTable /// </summary> /// <param name="sql">SQL语句</param> /// <param name="parameters">参数</param> /// <returns>DataTable结果</returns> /// <exception cref="ArgumentNullException">当sql为null或空时抛出</exception> public DataTable ExecuteDataTable(string sql, params DbParameter[] parameters) { if (string.IsNullOrWhiteSpace(sql)) throw new ArgumentNullException(nameof(sql), "SQL statement cannot be null or empty."); using (var connection = GetConnection()) { using (DbCommand command = CreateCommand(connection, sql, parameters)) { using (DbDataAdapter adapter = CreateDataAdapter(command)) { DataTable dt = new DataTable(); adapter.Fill(dt); return dt; } } } } /// <summary> /// 执行查询并返回DataTable(支持事务) /// </summary> public DataTable ExecuteDataTable(string sql, DbTransaction transaction, params DbParameter[] parameters) { if (string.IsNullOrWhiteSpace(sql)) throw new ArgumentNullException(nameof(sql)); using (DbCommand command = CreateCommand(transaction.Connection, sql, parameters)) { command.Transaction = transaction; using (DbDataAdapter adapter = CreateDataAdapter(command)) { DataTable dt = new DataTable(); adapter.Fill(dt); return dt; } } } /// <summary> /// 执行查询并返回第一行第一列的 /// </summary> /// <param name="sql">SQL语句</param> /// <param name="parameters">参数</param> /// <returns>结果</returns> /// <exception cref="ArgumentNullException">当sql为null或空时抛出</exception> public object ExecuteScalar(string sql, params DbParameter[] parameters) { if (string.IsNullOrWhiteSpace(sql)) throw new ArgumentNullException(nameof(sql), "SQL statement cannot be null or empty."); using (var connection = GetConnection()) { using (DbCommand command = CreateCommand(connection, sql, parameters)) { return command.ExecuteScalar(); } } } /// <summary> /// 执行存储过程 /// </summary> /// <param name="procedureName">存储过程名称</param> /// <param name="parameters">参数</param> /// <returns>DataTable结果</returns> /// <exception cref="ArgumentNullException">当procedureName为null或空时抛出</exception> public DataTable ExecuteStoredProcedure(string procedureName, params DbParameter[] parameters) { if (string.IsNullOrWhiteSpace(procedureName)) throw new ArgumentNullException(nameof(procedureName), "Procedure name cannot be null or empty."); using (var connection = GetConnection()) { using (DbCommand command = connection.CreateCommand()) { command.CommandText = procedureName; command.CommandType = CommandType.StoredProcedure; if (parameters != null && parameters.Length > 0) { foreach (var param in parameters) { if (param == null) continue; command.Parameters.Add(param); } } using (DbDataAdapter adapter = CreateDataAdapter(command)) { DataTable dt = new DataTable(); adapter.Fill(dt); return dt; } } } } /// <summary> /// 创建数据库命令 /// </summary> private DbCommand CreateCommand(DbConnection connection, string sql, params DbParameter[] parameters) { DbCommand command = connection.CreateCommand(); command.CommandText = sql; command.CommandType = CommandType.Text; if (parameters != null && parameters.Length > 0) { foreach (var param in parameters) { if (param == null) continue; command.Parameters.Add(param); } } return command; } /// <summary> /// 创建数据适配器 /// </summary> private DbDataAdapter CreateDataAdapter(DbCommand command) { switch (_databaseType) { case DatabaseType.SqlServer: return new SqlDataAdapter((SqlCommand)command); case DatabaseType.Oracle: return new OracleDataAdapter((OracleCommand)command); case DatabaseType.MySql: return new MySqlDataAdapter((MySqlCommand)command); default: throw new ArgumentException("Unsupported database type"); } } /// <summary> /// 创建参数 /// </summary> /// <param name="name">参数名</param> /// <param name="value">参数</param> /// <param name="dbType">参数类型</param> /// <param name="direction">参数方向</param> /// <returns>DbParameter实例</returns> /// <exception cref="ArgumentNullException">当name为null或空时抛出</exception> public DbParameter CreateParameter(string name, object value, DbType dbType, ParameterDirection direction = ParameterDirection.Input) { if (string.IsNullOrWhiteSpace(name)) throw new ArgumentNullException(nameof(name), "Parameter name cannot be null or empty."); DbParameter parameter; switch (_databaseType) { case DatabaseType.SqlServer: parameter = new SqlParameter(name, value ?? DBNull.Value); break; case DatabaseType.Oracle: parameter = new OracleParameter(name, value ?? DBNull.Value); break; case DatabaseType.MySql: parameter = new MySqlParameter(name, value ?? DBNull.Value); break; default: throw new ArgumentException("Unsupported database type"); } parameter.DbType = dbType; parameter.Direction = direction; return parameter; } /// <summary> /// 开始事务 /// </summary> /// <returns>DbTransaction实例</returns> public DbTransaction BeginTransaction() { var connection = GetConnection(); return connection.BeginTransaction(); } /// <summary> /// 执行事务操作 /// </summary> /// <param name="action">要执行的事务操作</param> /// <exception cref="ArgumentNullException">当action为null时抛出</exception> public void ExecuteInTransaction(Action<DbTransaction> action) { if (action == null) throw new ArgumentNullException(nameof(action), "Action cannot be null."); using (var connection = GetConnection()) { using (var transaction = connection.BeginTransaction()) { try { action(transaction); transaction.Commit(); } catch { try { transaction.Rollback(); } catch (Exception ex) { // 记录日志或处理回滚异常 throw new Exception("Transaction rollback failed.", ex); } throw; } } } } /// <summary> /// 释放资源 /// </summary> public void Dispose() { if (_connection != null) { try { if (_connection.State != ConnectionState.Closed) { _connection.Close(); } _connection.Dispose(); } catch { // 忽略释放过程中的异常 } finally { _connection = null; } } } } }
最新发布
08-13
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值