C# 如何封装存储过程调用

C# 如何封装存储过程调用,c#,C#,我有一个DAO类,我用它来做数据库操作。我有很多从不同方法/函数调用的存储过程。在每个函数/方法中,我都编写了一行代码,用于为SPs添加参数值。是否有任何方法可以封装它,以便所有函数/方法都可以调用这个封装的功能,将参数传递给不同的存储过程。我相信你们中的许多人都做过类似的事情。基本上,我试图避免在参数集合中添加参数的冗余语句 (我使用的是C#3.5)类似的东西可能是: public static IDataReader GetDataReader(string connectionString

我有一个DAO类,我用它来做数据库操作。我有很多从不同方法/函数调用的存储过程。在每个函数/方法中,我都编写了一行代码,用于为SPs添加参数值。是否有任何方法可以封装它,以便所有函数/方法都可以调用这个封装的功能,将参数传递给不同的存储过程。我相信你们中的许多人都做过类似的事情。基本上,我试图避免在参数集合中添加参数的冗余语句


(我使用的是C#3.5)

类似的东西可能是:

public static IDataReader GetDataReader(string connectionStringKey, string storedProcedure, Dictionary<string, object> parameters) {
    try {
        SqlCommand command = GetCommandWithConnection(connectionStringKey);
        command.CommandText = storedProcedure;
        command.CommandType = CommandType.StoredProcedure;
        foreach (var parameter in parameters ?? new Dictionary<string, object>())
            command.Parameters.AddWithValue(parameter.Key, parameter.Value);
        command.Connection.Open();
        return command.ExecuteReader();
    }
    catch (Exception e) {
        Log.Error(string.Format("Error in GetDataReader, executing sp: {0}", storedProcedure), e);
        throw;
    }     
}
private static SqlCommand GetCommandWithConnection(string connectionStringKey) {
    return new SqlConnection(GetConnectionString(connectionStringKey)).CreateCommand();
}
private static string GetConnectionString(string connectionStringKey) {
    return ConfigurationManager.ConnectionStrings[connectionStringKey].ToString();
}
公共静态IDataReader GetDataReader(字符串连接字符串键、字符串存储过程、字典参数){
试一试{
SqlCommand=GetCommandWithConnection(connectionStringKey);
command.CommandText=存储过程;
command.CommandType=CommandType.storedProcess;
foreach(参数中的var参数??新字典())
command.Parameters.AddWithValue(parameter.Key,parameter.Value);
command.Connection.Open();
return命令.ExecuteReader();
}
捕获(例外e){
Log.Error(string.Format(“GetDataReader中的错误,正在执行sp:{0}”,storedProcedure),e);
投掷;
}     
}
私有静态SqlCommand GetCommandWithConnection(字符串连接StringKey){
返回新的SqlConnection(GetConnectionString(connectionStringKey)).CreateCommand();
}
私有静态字符串GetConnectionString(字符串connectionStringKey){
返回ConfigurationManager.ConnectionString[connectionStringKey].ToString();
}
编辑:由于您添加了注释,说明您需要支持输出参数,下面是来自同一dal类的另一个方法:

public static T GetScalar<T>(string connectionStringKey, string storedProcedure, Parameters parameters) {
    try {
        List<Parameter> outs = null;
        SqlCommand command = GetCommandWithConnection(connectionStringKey);
        command.CommandText = storedProcedure;
        command.CommandType = CommandType.StoredProcedure;
        if (parameters != null) {
            outs = parameters.FindAll(p => p.Direction != ParameterDirection.Input);
            parameters.ForEach(p => command.Parameters.AddWithValue(p.Key, p.Value).Direction = p.Direction);
        }
        command.Connection.Open();
        object o = command.ExecuteScalar();
        T result = (o != null) ? (T)o : default(T);
        if (outs != null && outs.Count > 0) {
            foreach (Parameter parameter in outs) {
                SqlParameter sqlParameter = command.Parameters[parameter.Key];
                parameters[parameter.Key] = (sqlParameter.Value == DBNull.Value) ? null : sqlParameter.Value;
            }
        }
        command.Connection.Close();
        if (o == null && (typeof(T) == typeof(int)) && parameters != null && parameters.ContainsKey("RowCount"))
            result = (T)parameters["RowCount"];
        return result;
    }
    catch (Exception e) {
        Log.Error(String.Format("Error in GetScalar<{0}>, executing sp: {1}", typeof(T).Name, storedProcedure), e);
        throw;
    }
}
public static T GetScalar(字符串连接字符串key、字符串存储过程、参数){
试一试{
列表输出=空;
SqlCommand=GetCommandWithConnection(connectionStringKey);
command.CommandText=存储过程;
command.CommandType=CommandType.storedProcess;
if(参数!=null){
outs=parameters.FindAll(p=>p.Direction!=ParameterDirection.Input);
parameters.ForEach(p=>command.parameters.AddWithValue(p.Key,p.Value).Direction=p.Direction);
}
command.Connection.Open();
对象o=command.ExecuteScalar();
T结果=(o!=null)?(T)o:默认值(T);
if(outs!=null&&outs.Count>0){
foreach(参数输入输出){
SqlParameter SqlParameter=command.Parameters[parameter.Key];
参数[parameter.Key]=(sqlParameter.Value==DBNull.Value)?null:sqlParameter.Value;
}
}
command.Connection.Close();
如果(o==null&&(typeof(T)==typeof(int))&¶meters!=null&¶meters.ContainsKey(“行计数”))
结果=(T)参数[“行计数”];
返回结果;
}
捕获(例外e){
Log.Error(String.Format(“GetScalar中的错误,执行sp:{1}”),typeof(T.Name,storedProcedure),e);
投掷;
}
}
以及支持参数类:

public class Parameter{
    public string Key { get; private set; }
    public object Value { get; protected internal set; }
    public ParameterDirection Direction { get; protected internal set; }
    public Parameter(string key, object value) : this(key, value, ParameterDirection.Input) { }
    public Parameter(string key, object value, ParameterDirection direction){
        Key = key;
        Value = value;
        Direction = direction;
    }
}
public class Parameters : List<Parameter>{
    public Parameters() { }
    public Parameters(object o){
        Populate(o);
    }
    public void Add(string key, object value){
        if (ContainsKey(key))
            throw new Exception("Parameter with the specified key already exists.");
        Add(new Parameter(key, value));
    }
    public void Add(string key, object value, ParameterDirection direction){
        if (ContainsKey(key))
            throw new Exception("Parameter with the specified key already exists.");
        Add(new Parameter(key, value, direction));
    }
    public bool ContainsKey(string key){
        return (Find(p => p.Key == key) != null);
    }
    protected internal int GetIndex(string key){
        int? index = null;
        for (int i = 0; i < Count; i++){
            if (this[i].Key == key){
                index = i;
                break;
            }
        }
        if (index == null)
            throw new IndexOutOfRangeException("Parameter with the specified key does not exist.");
        return (int)index;
    }
    public object this[string key]{
        get { return this[GetIndex(key)].Value; }
        set { this[GetIndex(key)].Value = value; }
    }
    private void Populate<T>(T obj){
        foreach (KeyValuePair<string, object> pair in new ObjectProperties(obj, BindingFlags.Public | BindingFlags.Instance))
            Add(pair.Key, pair.Value);
    }
}
公共类参数{
公共字符串密钥{get;private set;}
公共对象值{get;受保护的内部集;}
公共参数方向方向{get;受保护的内部集;}
公共参数(字符串键,对象值):这个(键,值,参数方向.Input){}
公共参数(字符串键、对象值、参数方向){
钥匙=钥匙;
价值=价值;
方向=方向;
}
}
公共类参数:列表{
公共参数(){}
公共参数(对象o){
填充(o);
}
公共void添加(字符串键、对象值){
if(集装箱箱(钥匙))
抛出新异常(“具有指定键的参数已存在”);
添加(新参数(键、值));
}
public void Add(字符串键、对象值、参数方向){
if(集装箱箱(钥匙))
抛出新异常(“具有指定键的参数已存在”);
添加(新参数(键、值、方向));
}
公共bool ContainsKey(字符串键){
返回(Find(p=>p.Key==Key)!=null);
}
受保护的内部int-GetIndex(字符串键){
int?索引=null;
for(int i=0;i
谢谢您的建议。我还试图弄清楚如何传递参数是In或out类型的信息?实际上,我通过使用通用自定义参数列表的实际dal中的方法简化了这一点。我在示例中使用了一个字典,但您也可以有一个列表,其中的参数封装了您的方向和其他属性。非常感谢这段代码。我想我会从这里赶上:)