2009-08-27 5 views
3

J'ai une classe DAO que j'utilise pour effectuer des opérations de base de données. J'ai beaucoup de procédures stockées que j'appelle de différentes méthodes/fonctions. Dans chaque fonction/méthode, j'écris une seule ligne pour ajouter des valeurs de paramètres pour les SP. Est-il possible que je puisse encapsuler ceci de sorte que toutes les fonctions/méthodes peuvent appeler ceci une fonctionnalité encapsulée pour passer des paramètres à la procédure stockée différente. Je suis sûr que beaucoup d'entre vous ont travaillé sur quelque chose de similaire. Fondamentalement, j'essaie d'éviter les instructions redondantes pour l'ajout de paramètres à la collecte de paramètres.Comment encapsuler l'appel de procédure stockée

(J'utilise C# 3.5)

Répondre

1

Quelque chose comme ça peut-être:

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: Vous avez ajouté des commentaires à vous dire besoin de soutenir params de sortie, Heres une autre méthode de la même dal classe:

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

Et les classes de paramètres: le soutien

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

Merci pour cette suggestion. J'essaie également de comprendre comment transmettre des informations qu'un paramètre est de type In ou Out? – pradeeptp

+0

En fait, j'ai simplifié cela à partir de méthodes dans un vrai dal où nous utilisons une liste de paramètres personnalisés génériques. J'ai utilisé un dictionnaire dans l'exemple mais vous pourriez tout aussi bien avoir une liste où le paramètre encapsule votre direction et d'autres propriétés. – grenade

+0

Un grand merci pour ce code. Je pense que je vais rattraper d'ici :) – pradeeptp