2017-10-06 4 views
0

Ma question est la suivante: Quelle est la manière la plus efficace de traiter les requêtes postgresql dans une nouvelle classe/méthode qui ont des requêtes SQL, des paramètres et des valeurs de retour différents?Création d'une classe qui gère les requêtes postgresql en C#

Par exemple:

NpgsqlCommand ukupno_sati = new NpgsqlCommand("begin;select cast(radni_sati.sati_rada as time) from radni_sati where [email protected]_id " + 
        " and extract(month from radni_sati.datum)[email protected]_broj and extract(year from radni_sati.datum)[email protected];commit;",conn); 
        ukupno_sati.Parameters.AddWithValue("@zaposlenik_id", dtIme_prezime_odjel_bolovanje_godisnji.Rows[i][0]); 
        ukupno_sati.Parameters.AddWithValue("@mjesec_broj", mjesec_broj); 
        ukupno_sati.Parameters.AddWithValue("@godina", godina); 
        NpgsqlDataAdapter dz = new NpgsqlDataAdapter(ukupno_sati); 
        DataTable UkupnoSati = new DataTable(); 
        dz.Fill(UkupnoSati); 

ou

NpgsqlCommand godisnji = new NpgsqlCommand("begin;select count(*) from godisnji where extract(month from godisnji.datum)" + 
        "[email protected]_broj and extract(year from godisnji.datum)[email protected] and [email protected]_id;commit;",conn); 
        godisnji.Parameters.AddWithValue("@mjesec_broj", mjesec_broj.ToString()); 
        godisnji.Parameters.AddWithValue("@godina", godina.ToString()); 
        godisnji.Parameters.AddWithValue("@zaposlenik_id", dtIme_prezime_odjel_bolovanje_godisnji.Rows[i][0]); 
        int iskoristeni_godisnji = Convert.ToInt32(godisnji.ExecuteScalar()); 

Donc, mon point est: Puis-je faire une méthode qui gère différentes requêtes avec des valeurs de retour et le nombre de paramètres différents selon une des requêtes telles que montré dans les exemples?

Répondre

1

Vous pouvez utiliser le même technique que j'ai utilisé pour écrire ADONETHelper.
Vérifiez également le code du projet intitulé HowToUseADONETHelper.

La principale méthode est la suivante:

T Execute<T>(string sql, CommandType commandType, Func<IDbCommand, T> function, params IDbDataParameter[] parameters) 
{ 
    using (var con = new TConnection()) // replace TConnection with your connection object 
    { 
     con.ConnectionString = _ConnectionString; 
     using (var cmd = new NpgsqlCommand()) 
     { 
      cmd.CommandText = sql; 
      cmd.Connection = con; 
      cmd.CommandType = commandType; 
      if (parameters.Length > 0) 
      { 
       foreach (var parameter in parameters) 
       { 
        cmd.Parameters.Add(parameter); 
       } 
      } 
      con.Open(); 
      return function(cmd); 
     } 
    } 
} 

Notez que la méthode Execute accepte un argument de type Func<IDbCommand, T> - ce fait vous permet de faire toutes sortes de choses intéressantes:

Ensuite, vous pouvez utiliser certains d'autres exécuter pour vous simplifier la surcharge code:

Execute non requête:

public int ExecuteNonQuery(string sql, CommandType commandType, params IDbDataParameter[] parameters) 
{ 
    return Execute<int>(sql, commandType, c => c.ExecuteNonQuery(), parameters); 
} 

C'est assez simple - la fonction que vous envoyez à la méthode Execute est simplement c => c.ExecuteNonQuery() - et comme vous le savez, le ExecuteNonQuery dans l'interface IDbCommand retourne un int, donc Execute sera également de retour int.

Exécuter Scalar:

public T ExecuteScalar<T>(string sql, CommandType commandType, params IDbDataParameter[] parameters) 
{ 
    return Execute<T>(sql, commandType, c => 
    { 
     var returnValue = c.ExecuteScalar(); 
     return (returnValue != null && returnValue != DBNull.Value && returnValue is T) 
     ? (T)returnValue 
     : default(T); 
    }, parameters); 
} 

Ici, la fonction est un peu plus compliqué. Le ExecuteScalar() de IDbCommand renvoie un Object. Ce Object peut être nul, il peut être DBNull, ou il peut s'agir d'une chaîne, int, ou n'importe quel type de données pris en charge par votre base de données. Donc, ce que je fais est d'utiliser une condition qui renvoie le default de T lorsque la valeur retournée par ExecuteScalar est null ou DBNull, ou simplement le object de lancer à T et le renvoyer.

Execute Lecteur:

// Here, you do the actuall reading from the dataReader in the populate function 
public bool ExecuteReader(string sql, CommandType commandType, Func<IDataReader, bool> populate, params IDbDataParameter[] parameters) 
{ 
    return Execute<bool>(sql, commandType, c => populate(c.ExecuteReader()), parameters); 
} 

Assez simple, non?la fonction populate pourrait ressembler à ceci:

bool Populate(IDataReader reader) 
{ 
    var obj = new MyClass(); 
    while(reader.Read()) 
    { 
     obj.PropertyA = reader.GetValueOrDefault("A"); // That method is written in the IDataReaderExtestion class in ADONETHelper 
    } 

    return true; 
} 

et remplir un ensemble de données:

public DataSet FillDataSet(string sql, CommandType commandType, params IDbDataParameter[] parameters) 
{ 
    return Execute<DataSet>(sql, commandType, c => FillDataSet(c), parameters); 
} 

private DataSet FillDataSet(IDbCommand command) 
{ 
    var dataSet = new DataSet(); 
    using (var adapter = new TAdapter()) 
    { 
     adapter.SelectCommand = command; 
     adapter.Fill(dataSet); 
    } 
    return dataSet; 
} 

En fait, je aurais pu faire la même chose ici avec l'exécution de lecteur, et d'écrire la méthode FillDataSet comme une expression lambda, je ne me souviens pas pourquoi j'ai décidé d'écrire le FillDataSet comme une méthode différente. Cependant, c'est la méthode que je passe en tant qu'argument function à la méthode Execute. Il utilise simplement un DataAdapter pour remplir l'ensemble de données. Notez que vous devez changer le TAdapter en NpgsqlDataAdapter dans votre cas.

+0

Aimez votre réponse, aimerais voir plus de code commenté si possible, car je peux le copier/coller/le modifier sans comprendre certaines parties, mais ce n'est pas ce que je veux. –

+0

Si vous me dites quelles parties vous ne comprenez pas je peux l'expliquer ... –

+0

La chose principale im confus à propos de est "Execute Scalar" et "dataset", ne comprends pas certaines parties de l'appel de retour dans ces méthodes, donc si vous serait si aimable de commenter ces parties, serait reconnaissant =) –

0

Si vous cherchez à retourner des données Tableau et entier à partir d'une méthode alors son possible seule méthode en utilisant la table de données type de retour et entier comme paramètre out (vous pouvez lire here)

+0

Son tableau de données OR entier OU quelque chose d'autre, dans de rares cas, je vais devoir retourner les deux, mais merci pour info. –