2009-08-27 2 views
3

У меня есть класс DAO, который я использую для выполнения операций с базой данных. У меня есть много хранимых процедур, которые я вызываю из разных методов/функций. В каждой функции/Method я пишу одну строку для добавления значений параметров для SP. Можно ли каким-либо образом инкапсулировать это, чтобы все функции/Методы могли вызвать эту инкапсулированную функциональность для передачи параметров в другую хранимую процедуру. Я уверен, что многие из вас работали над чем-то похожим на это. В основном я стараюсь избегать избыточных операторов для добавления параметров в набор параметров.Как инкапсулировать вызов хранимой процедуры

(я использую C# 3.5)

ответ

1

Что-то вроде этого, может быть:

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(); 
} 

Edit: так как вы добавили комментарии, чтобы сказать вам необходимо поддерживать выходные Params, Херес другой метод из того же даль класс:

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 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); 
    } 
} 
+0

Спасибо за это предложение. Я также пытаюсь выяснить, как передать информацию о том, что параметр имеет тип In или Out? – pradeeptp

+0

Я фактически упростил это из методов в реальном dal, где мы используем общий список настраиваемых параметров. Я использовал словарь в примере, но вы могли бы также иметь список , где параметр инкапсулирует ваше направление и другие свойства. – grenade

+0

Большое спасибо за этот код. Я думаю, что догоню отсюда :) – pradeeptp