创建一个在C#中处理postgresql查询的类

时间:2017-10-06 08:46:45

标签: c# sql postgresql methods

我的问题是:在具有不同SQL查询,参数和返回值的新类/方法中处理大量postgresql查询的最有效方法是什么?

例如:

NpgsqlCommand ukupno_sati = new NpgsqlCommand("begin;select cast(radni_sati.sati_rada as time) from radni_sati where zaposlenik_id=@zaposlenik_id " +
                    " and extract(month from radni_sati.datum)=@mjesec_broj and extract(year from radni_sati.datum)=@godina;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);

NpgsqlCommand godisnji = new NpgsqlCommand("begin;select count(*) from godisnji where extract(month from godisnji.datum)" +
                    "=@mjesec_broj and extract(year from godisnji.datum)=@godina and zaposlenik_id=@zaposlenik_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());

所以我的观点是:我可以创建一个方法来处理具有不同返回值和不同参数数量的不同查询,具体取决于示例中显示的查询吗?

2 个答案:

答案 0 :(得分:1)

您可以使用我用于撰写ADONETHelper的相同技巧 另外,请查看名为HowToUseADONETHelper的项目代码。

主要方法是:

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

请注意,Execute方法接受类型为Func<IDbCommand, T>的参数 - 这个事实允许您执行各种有趣的事情:

然后您可以使用其他一些执行重载来简化代码:

执行非查询:

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

这非常简单 - 您发送到Execute方法的函数只是c => c.ExecuteNonQuery() - 如您所知,IDbCommand接口中的ExecuteNonQuery返回int ,因此Execute也会返回int

执行标量:

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

这里的功能有点复杂。 ExecuteScalar()的{​​{1}}会返回IDbCommandObject可能为null,可能是DBNull,也可能是字符串,int或数据库支持的任何数据类型。所以我所做的是使用一个条件,当Object返回的值为defaultT时,返回ExecuteScalar的{​​{1}},或者简单地转换{ {1}} null并返回。

执行读者:

DBNull

非常简单,对吧? populate函数可能如下所示:

object

填写数据集:

T

基本上,我可以在这里完成与执行阅读器相同的操作,并将// 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); } 方法写为lambda表达式,我不记得我为什么决定编写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; } 作为一种不同的方法。但是,这是我作为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; } 方法的FillDataSet参数传递的方法。它只是使用DataAdapter来填充数据集。请注意,您应该将FillDataSet更改为function

答案 1 :(得分:0)

如果您希望从方法返回数据表和整数,那么可以在单个方法中使用数据表作为返回类型,将整数作为out参数(您可以阅读here