Skip to main content
9 of 16
deleted 6 characters in body

C# SQL query builder to fill DataTable

I'm trying to optimize my code and in the process of doing that I made a class Query_builder that handles SQL queries. That class has couple of methods: ExecuteScalar (execute scalar queries that mainly return int or long as a type), FillDataTable(used to fill Datatable with data from SQL tables) and the main one Execute(used for "shaping" the query). My plan backfired on me and I ended up slowing down my reports in app (time it takes to fill a full monthly report).

Class Query_builder:

 class Query_builder
{
    public T Execute<T>(string sql, CommandType commandType, Func<NpgsqlCommand, T> function, List<NpgsqlParameter> parameters)
    {
        
        using (NpgsqlConnection conn = Konekcija_na_server.Spajanje("spoji"))  //created a connection with postgresql database
        {
            using (var cmd = new NpgsqlCommand(sql, conn) { CommandType = commandType }) //using a NpgsqlCommand with query as "sql", "conn" as connection and commandType as a type of query.
            {
                if (parameters.Count > 0 ) //if there are any parameters in the list
                {
                    foreach (var parameter in parameters)
                    {
                        cmd.Parameters.AddWithValue(parameter.ParameterName,parameter.Value);  //add parameter to the referenced place 
                    }
                }                    
                return function(cmd); 
            }
        }            
    }
    
    public T ExecuteScalar<T>(string sql, CommandType commandType, List<NpgsqlParameter> parameters)
    {
       return Execute<T>(sql, commandType, c => { //return to Execute<T> with parameters: "sql","commandType",lamba expression as function and parameters.
            var returnValue =c.ExecuteScalar();  //execute ExecuteScalar and get the return value from Execute<T>
            return (returnValue != null && returnValue != DBNull.Value && returnValue is T) //return if not null or DBNull
            ? (T)returnValue : default(T); //if condition is true, return "returnValue", if not return default of declared type
        }, parameters);          
    }

    public DataTable FillDataTable(string sql, CommandType commandType, List<NpgsqlParameter> parameters)
    {
        return Execute<DataTable>(sql, commandType, c => FillDataTable(c), parameters);                                                                                          
    }

    private DataTable FillDataTable(NpgsqlCommand command)
    {
        using (NpgsqlConnection conn = Konekcija_na_server.Spajanje("spoji")) //using the connection to postgresql database
        {
            DataTable dataTable = new DataTable(); //create a new datatable
            using (NpgsqlDataAdapter adapter = new NpgsqlDataAdapter(command)) //create an adapted with sql command as "command"
            {
                command.Connection = conn; //connection for executing is "conn"
                adapter.Fill(dataTable); //fill the adapted with result DataTable from sql query
            }
            return dataTable;                 
        }          
    }  
}

The way I call the methods (for ex. if I need a DataTable as return):

komanda = "begin;select zaposlenik_id,ime,prezime,odjel,bolovanje,godisnji from zaposlenici " +
                              "order by zaposlenik_id;commit;"; //sql command
                    listaParametara.Clear(); //clearing the list if any parameters are left from last query
                    dt = instanca.FillDataTable(komanda, CommandType.Text, listaParametara); //"dt" is Datatable, "instanca" is an instance of Query_builder class and it calls a method FillDataTable

For generating a report I'm calling class Query_builder 14 times, for 14 different queries and in the background are calculations for example: generating work hours from some of those queries and filling one column of datagridview with that data.

Before making a class Query_builder my queries used to look different and time for generating report was much shorted:

NpgsqlCommand bolovanje_godisnji = new NpgsqlCommand("begin;select zaposlenik_id,ime,prezime,odjel,bolovanje,godisnji from zaposlenici " +
                          "order by zaposlenik_id;commit;", conn);
                    NpgsqlDataAdapter da = new NpgsqlDataAdapter(bolovanje_godisnji);
                    DataTable dz = new DataTable();
                    da.Fill(dz);

I assume the problem is in generating SQL queries coz my logic behind and data manipulation stayed the same with a little bit of tweaks ( nothing that would slow down process so much).

I was trying to get an example of how much it takes me to fill the full report. My results are following: In this build with class Query_builder where that class acts as core of SQL query generation, It takes about 00:01:16 sec to execute the whole report and fill datagridview with it. On my last build without general class for SQL queries, the whole report would calculate and fill the datagridview within 00:00:10 seconds.

EDIT:

My whole report starts by checking the checkbox checkBoxMjesecni (represents monthly report) and selecting an item from combobox comboBoxMjesec (list that fills comboBoxMjesec represents months). After its all filled I look at the role the current user has (admin, one department or another) and assign the proper limitations depending on a role (in this case, admin will have full report of all employees and if someone else from some other department logs in he will have have monthly report based on his department):

if (checkBoxMjesecni.Checked == true)
            {
            #region Odredjivanje mjeseca //determining what month is selected
            string mjesec = comboBoxMjesec.GetItemText(comboBoxMjesec.SelectedItem);
                string mjesec_broj = "";
                if (mjesec == "Siječanj") mjesec_broj = "1";
                else if (mjesec == "Veljača") mjesec_broj = "2";
                else if (mjesec == "Ožujak") mjesec_broj = "3";
                else if (mjesec == "Travanj") mjesec_broj = "4";
                else if (mjesec == "Svibanj") mjesec_broj = "5";
                else if (mjesec == "Lipanj") mjesec_broj = "6";
                else if (mjesec == "Srpanj") mjesec_broj = "7";
                else if (mjesec == "Kolovoz") mjesec_broj = "8";
                else if (mjesec == "Rujan") mjesec_broj = "9";
                else if (mjesec == "Listopad") mjesec_broj = "10";
                else if (mjesec == "Studeni") mjesec_broj = "11";
                else if (mjesec == "Prosinac") mjesec_broj = "12";
                #endregion

                string godina = comboBoxMjesecGodina.GetItemText(comboBoxMjesecGodina.SelectedItem); //gets what year is set
                //if admin is logged in
                if (odjel_id_prop == 0) //odjel_id_prop represents an propery that is assigned after logging in, says: "this user is admin, he has deparment_id=0"
                {
                    komanda = "begin;select zaposlenik_id,ime,prezime,odjel,bolovanje,godisnji from zaposlenici " +
                              "order by zaposlenik_id;commit;";
                    listaParametara.Clear();  
                    dt = instanca.FillDataTable(komanda, CommandType.Text, listaParametara); 
                }
                //if another department is logged in
                else if (odjel_id_prop == 1)
                {
                    komanda = "begin;select zaposlenik_id,ime,prezime,odjel,bolovanje,godisnji from zaposlenici " +
                              " where (odjel_id=1 or odjel_id=2 or odjel_id=5 or odjel_id=6) order by zaposlenik_id;commit;";
                    //odjel_id represents deparment_id
                    listaParametara.Clear(); 
                    dt = instanca.FillDataTable(komanda, CommandType.Text, listaParametara); 

                    //if another department is logged in
                }
                else if (odjel_id_prop == 7)
                {
                    komanda = "begin;select zaposlenik_id,ime,prezime,odjel,bolovanje,godisnji from zaposlenici " +
                              " where odjel_id = 7 order by zaposlenik_id;commit;";
                    listaParametara.Clear(); 
                    dt = instanca.FillDataTable(komanda, CommandType.Text, listaParametara); //popuni dt tablicu s podacima koje vrati metoda FillDataTable()

                }
                //if anyone else is logged in
                else
                {
                    komanda = "begin;select zaposlenik_id,ime,prezime,odjel,bolovanje,godisnji from zaposlenici " +
                              " where odjel_id = @odjel_id order by zaposlenik_id;commit;";
                    listaParametara.Add(new NpgsqlParameter { ParameterName = "@odjel_id", Value = odjel_id_prop });
                    dt = instanca.FillDataTable(komanda, CommandType.Text, listaParametara);
                    listaParametara.Clear();
                }                   

After I found out who is logged in and gave proper query for it and fill the datatable dt with return value of query:

for (int i = 0; i < dt.Rows.Count; i++) //dt is the datatable that was filled with data depending on the role of user that is logged in
                {
                    //query that returns how many times an employee logged in in that month of a year
                    komanda = "begin;select count(*) from radni_sati where zaposlenik_id=@zaposlenik_id and " +
                              " extract(month from datum)=@mjesec_broj and extract(year from datum)=@godina ;commit;";
                    listaParametara.Add(new NpgsqlParameter { ParameterName = "@mjesec_broj", Value = mjesec_broj }); //month we are making report on 
                    listaParametara.Add(new NpgsqlParameter { ParameterName = "@godina", Value = godina }); //year we are making report on
                    listaParametara.Add(new NpgsqlParameter { ParameterName = "@zaposlenik_id", Value = dt.Rows[i][0] }); //employee id
                    long ZapisUMjesecu = instanca.ExecuteScalar<long>(komanda, CommandType.Text, listaParametara);
                    listaParametara.Clear();

                    //returns the department_id from current employee 
                    komanda = "begin;select odjel_id from zaposlenici where zaposlenik_id=@zaposlenik_id ;commit;";
                    listaParametara.Add(new NpgsqlParameter { ParameterName = "@zaposlenik_id", Value = dt.Rows[i][0] });
                    int OdjelID = instanca.ExecuteScalar<int>(komanda, CommandType.Text, listaParametara);
                    listaParametara.Clear();

                    //if that employee has atlest 1 day of work
                    if (ZapisUMjesecu > 0)
                    {
                        //return number of sick days he had
                        komanda = "begin;select count(*) from bolovanje where extract(month from bolovanje.datum)" +
                                  "=@mjesec_broj and extract(year from bolovanje.datum)=@godina and zaposlenik_id=@zaposlenik_id ;commit;";
                        listaParametara.Add(new NpgsqlParameter { ParameterName = "@mjesec_broj", Value = mjesec_broj });
                        listaParametara.Add(new NpgsqlParameter { ParameterName = "@godina", Value = godina });
                        listaParametara.Add(new NpgsqlParameter { ParameterName = "@zaposlenik_id", Value = dt.Rows[i][0] });
                        long iskoristeno_bolovanje = instanca.ExecuteScalar<long>(komanda, CommandType.Text, listaParametara);
                        listaParametara.Clear();

                        //returns all the dates that employee was sick 
                        komanda = "begin;select datum from bolovanje where extract(month from bolovanje.datum)" +
                                  "=@mjesec_broj and extract(year from bolovanje.datum)=@godina and zaposlenik_id=@zaposlenik_id ;commit;";
                        listaParametara.Add(new NpgsqlParameter { ParameterName = "@zaposlenik_id", Value = dt.Rows[i][0] });
                        listaParametara.Add(new NpgsqlParameter { ParameterName = "@mjesec_broj", Value = mjesec_broj });
                        listaParametara.Add(new NpgsqlParameter { ParameterName = "@godina", Value = godina });
                        DataTable DatumiBolovanja = instanca.FillDataTable(komanda, CommandType.Text, listaParametara);
                        listaParametara.Clear();

                        //return number of holidays he had
                        komanda = "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;";
                        listaParametara.Add(new NpgsqlParameter { ParameterName = "@mjesec_broj", Value = mjesec_broj });
                        listaParametara.Add(new NpgsqlParameter { ParameterName = "@godina", Value = godina });
                        listaParametara.Add(new NpgsqlParameter { ParameterName = "@zaposlenik_id", Value = dt.Rows[i][0] });
                        long iskoristeni_godisnji = instanca.ExecuteScalar<long>(komanda, CommandType.Text, listaParametara);
                        listaParametara.Clear();

                        //returns all the dates that employee was on holiday
                        komanda = "begin;select datum from godisnji where extract(month from godisnji.datum)" +
                                  "=@mjesec_broj and extract(year from godisnji.datum)=@godina and zaposlenik_id=@zaposlenik_id ;commit;";
                        listaParametara.Add(new NpgsqlParameter { ParameterName = "@zaposlenik_id", Value = dt.Rows[i][0] });
                        listaParametara.Add(new NpgsqlParameter { ParameterName = "@mjesec_broj", Value = mjesec_broj });
                        listaParametara.Add(new NpgsqlParameter { ParameterName = "@godina", Value = godina });
                        DataTable DatumiGodisnjeg = instanca.FillDataTable(komanda, CommandType.Text, listaParametara);
                        listaParametara.Clear();



                        //returns a number of days that employee was working
                        komanda = "begin;select count(*) from radni_sati where zaposlenik_id=@zaposlenik_id" +
                                  " and (dolazak is not null and odlazak is not null and sati_rada is not null) and extract(month from radni_sati.datum)" +
                                  "=@mjesec_broj and extract(year from radni_sati.datum)=@godina group by zaposlenik_id order by zaposlenik_id;commit;";
                        listaParametara.Add(new NpgsqlParameter { ParameterName = "@mjesec_broj", Value = mjesec_broj });
                        listaParametara.Add(new NpgsqlParameter { ParameterName = "@godina", Value = godina });
                        listaParametara.Add(new NpgsqlParameter { ParameterName = "@zaposlenik_id", Value = dt.Rows[i][0] });
                        long redovi = instanca.ExecuteScalar<long>(komanda, CommandType.Text, listaParametara);
                        listaParametara.Clear();

                        
                        //calculate number of hours that employee was working in that month                 
                        komanda = "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;";
                        listaParametara.Add(new NpgsqlParameter { ParameterName = "@zaposlenik_id", Value = dt.Rows[i][0] });
                        listaParametara.Add(new NpgsqlParameter { ParameterName = "@mjesec_broj", Value = mjesec_broj });
                        listaParametara.Add(new NpgsqlParameter { ParameterName = "@godina", Value = godina });
                        DataTable UkupnoSati = instanca.FillDataTable(komanda, CommandType.Text, listaParametara);
                        listaParametara.Clear();

When I'm done with that I calculate how many workhours an employee had in a month:

#region Izracun Sati rada //calculation of workhours per employee
                        TimeSpan Ukupno_sati = TimeSpan.Zero;
                        TimeSpan Ukupno_sati_prosjek = TimeSpan.Zero;
                        for (int x = 0; x < UkupnoSati.Rows.Count; x++) 
                        {
                            string ukupno_prijelazni = Convert.ToString(UkupnoSati.Rows[x][0]); //pretvara zapis u string
                            string Ukupno_sati_string = Convert.ToString(UkupnoSati.Rows[x][0]).Substring(ukupno_prijelazni.IndexOf(' ') + 1); //takes only time from timestamp format
                            if (Ukupno_sati_string != "") //if its valid
                            {
                                Ukupno_sati += TimeSpan.Parse(Ukupno_sati_string); //add time to sum of hours (Ukupno_Sati)
                                Ukupno_sati_prosjek += TimeSpan.Parse(Ukupno_sati_string); //later used for calculating average worktime
                            }

                            if (UkupnoSati.Rows.Count > 0) //if that person worked that month
                            {
                                //format a string in "hh:mm:ss" format
                                suma = string.Format("{0}:{1}:{2}", ((int)Ukupno_sati.TotalHours), Ukupno_sati.Minutes, Ukupno_sati.Seconds);
                            }

                        }

                    #endregion 

Now Im calculating time of sick days and holidays per employee:

                            string nazivDana = ""; //name of the day in a week
                        string bolovanje_vrijeme = ""; //sick days
                        string godisnji_vrijeme = ""; //holidays
                        TimeSpan ts_bolovanje_vrijeme = TimeSpan.Zero;
                        TimeSpan ts_godisnji_vrijeme = TimeSpan.Zero;
                    if (DatumiBolovanja.Rows.Count > 0) //if an employee has atlest 1 sick day in that month
                    {
                        //calculating sick days
                        for (int x = 0; x < DatumiBolovanja.Rows.Count; x++)
                        {
                            DateTime datum = Convert.ToDateTime(DatumiBolovanja.Rows[x][0]); //takes date
                            nazivDana = datum.ToString("dddd"); //takes the date and turns it into name of the day
                            //everything in if, else if and else loops is calculation depending on department_id and day of the week
                            
                            if (nazivDana != "Subota" && (OdjelID == 1 || OdjelID == 2 || OdjelID == 3 || OdjelID == 5 || OdjelID == 6))
                            {
                                ts_bolovanje_vrijeme = TimeSpan.FromHours(8);
                                ts_bolovanje_vrijeme += TimeSpan.FromTicks(ts_bolovanje_vrijeme.Ticks);                                                                    
                                bolovanje_vrijeme = string.Format("{0}:{1}:{2}", ((int)ts_bolovanje_vrijeme.TotalHours), ts_bolovanje_vrijeme.Minutes.ToString("00"), ts_bolovanje_vrijeme.Seconds.ToString("00"));
                            }
                            else if (nazivDana != "Subota" && (OdjelID == 4 || OdjelID == 7 || OdjelID == 8 || OdjelID == 9 || OdjelID == 10))
                            {
                                ts_bolovanje_vrijeme = TimeSpan.FromHours(7);
                                ts_bolovanje_vrijeme += TimeSpan.FromTicks(ts_bolovanje_vrijeme.Ticks);                                                                     
                                bolovanje_vrijeme = string.Format("{0}:{1}:{2}", ((int)ts_bolovanje_vrijeme.TotalHours), ts_bolovanje_vrijeme.Minutes.ToString("00"), ts_bolovanje_vrijeme.Seconds.ToString("00"));
                            }
                            else if (nazivDana == "Subota")
                            {
                                ts_bolovanje_vrijeme = TimeSpan.FromHours(5);
                                ts_bolovanje_vrijeme += TimeSpan.FromTicks(ts_bolovanje_vrijeme.Ticks);                                                                    
                                bolovanje_vrijeme = string.Format("{0}:{1}:{2}", ((int)ts_bolovanje_vrijeme.TotalHours), ts_bolovanje_vrijeme.Minutes.ToString("00"), ts_bolovanje_vrijeme.Seconds.ToString("00"));
                            }
                        }

                    }
                    else bolovanje_vrijeme = string.Format("00:00:00"); //if an employee had no sick days 

                    //same goes for holidays, same logic
                    if (DatumiGodisnjeg.Rows.Count > 0)
                    {
                        for (int x = 0; x < DatumiGodisnjeg.Rows.Count; x++)
                        {
                            DateTime datum = Convert.ToDateTime(DatumiGodisnjeg.Rows[x][0]);
                            nazivDana = datum.ToString("dddd");
                            if (nazivDana != "Subota" && (OdjelID == 1 || OdjelID == 2 || OdjelID == 3 || OdjelID == 5 || OdjelID == 6))
                            {
                                ts_godisnji_vrijeme = TimeSpan.FromHours(8); 
                                ts_godisnji_vrijeme += TimeSpan.FromTicks(ts_godisnji_vrijeme.Ticks);                                                                                                        
                                godisnji_vrijeme = string.Format("{0}:{1}:{2}", ((int)ts_godisnji_vrijeme.TotalHours), ts_godisnji_vrijeme.Minutes.ToString("00"), ts_godisnji_vrijeme.Seconds.ToString("00"));
                            }
                            else if ((nazivDana != "Subota" && (OdjelID == 4 || OdjelID == 7 || OdjelID == 8 || OdjelID == 9 || OdjelID == 10)))
                            {
                                ts_godisnji_vrijeme = TimeSpan.FromHours(7); 
                                ts_godisnji_vrijeme += TimeSpan.FromTicks(ts_godisnji_vrijeme.Ticks);                                                                    
                                godisnji_vrijeme = string.Format("{0}:{1}:{2}", ((int)ts_godisnji_vrijeme.TotalHours), ts_godisnji_vrijeme.Minutes.ToString("00"), ts_godisnji_vrijeme.Seconds.ToString("00"));
                            }
                            else if (nazivDana == "Subota")
                            {
                                ts_godisnji_vrijeme = TimeSpan.FromHours(5); 
                                ts_godisnji_vrijeme += TimeSpan.FromTicks(ts_godisnji_vrijeme.Ticks);                                                                   
                                godisnji_vrijeme = string.Format("{0}:{1}:{2}", ((int)ts_godisnji_vrijeme.TotalHours), ts_godisnji_vrijeme.Minutes.ToString("00"), ts_godisnji_vrijeme.Seconds.ToString("00"));
                            }
                        }
                    }
                    else godisnji_vrijeme = string.Format("00:00:00");

Next calculations are official feast days which are stored in a list called Blagdani_lista :

 #region Izracun blagdana
                        //calculation of feast days
                        DateTime danasnji_datum = DateTime.Now.Date; //current date
                        string Ukupno_vrijeme = ""; 
                        TimeSpan Ukupno = TimeSpan.Zero; //sum
                        double Ukupuno_sekundi_double = 0;
                        //sum of workhours+sick days+holidays
                        Ukupuno_sekundi_double = Ukupno_sati.TotalMilliseconds + ts_bolovanje_vrijeme.TotalMilliseconds + ts_godisnji_vrijeme.TotalMilliseconds;
                        double blagdani_ukupno = 0; //feast days
                        TimeSpan Blagdani_vrijeme = TimeSpan.Zero;
                        string blagdani_ispis = ""; //string for formating
                        int brojac = 0; //counter for checking does a person have a "right" to have calculation of feast days in summ of hours

                        foreach (var item in Blagdani.Blagdani_lista) //foreach feast day in list
                        {

                            if (item.datum.Month == Convert.ToInt32(mjesec_broj)) //if that feast day is in the month we are making report for
                            {

                                //calculate the department_id
                                komanda = "begin;select odjel_id from zaposlenici where zaposlenik_id=@zaposlenik_id;commit;";
                                listaParametara.Add(new NpgsqlParameter { ParameterName = "@zaposlenik_id", Value = dt.Rows[i][0] });
                                int odjelID = instanca.ExecuteScalar<int>(komanda, CommandType.Text, listaParametara);
                                listaParametara.Clear();

                                //check is the employee on sick day when the feast day is                            
                                komanda = "begin;select count(*) from bolovanje where datum=@datum and " +
                                          " zaposlenik_id=@zaposlenik_id;commit;";
                                listaParametara.Add(new NpgsqlParameter { ParameterName = "@datum", Value = item.datum.ToString("dd/MM/yyyy", CultureInfo.InvariantCulture) });
                                listaParametara.Add(new NpgsqlParameter { ParameterName = "@zaposlenik_id", Value = dt.Rows[i][0] });
                                long BlagdanBolovanje = instanca.ExecuteScalar<long>(komanda, CommandType.Text, listaParametara);
                                listaParametara.Clear();



                                int rezultat = danasnji_datum.CompareTo(item.datum); //compare did the feast day pass the current date or is it today or is it comming
                                //if the feast day passed or if its today and its not sunday and he is not on his sick day and he belongs to some of the deparments listed
                                // same type of calculation is made as for sick days or holidays
                                if ((rezultat == 0 || rezultat == 1) && item.dan_u_tjednu != "Subota" && BlagdanBolovanje != 1 && (odjelID == 4 || odjelID == 7 || odjelID == 8 || odjelID == 9 || odjelID == 10))
                                {
                                    brojac++; //increase the counter 
                                    TimeSpan Blagdan = TimeSpan.FromHours(7);
                                    Ukupuno_sekundi_double += Blagdan.TotalMilliseconds;
                                    Ukupno = TimeSpan.FromMilliseconds(Ukupuno_sekundi_double);
                                    Ukupno_vrijeme = string.Format("{0}:{1}:{2}", ((int)Ukupno.TotalHours), Ukupno.Minutes, Ukupno.Seconds);

                                    blagdani_ukupno += Blagdan.TotalMilliseconds;
                                    Blagdani_vrijeme = TimeSpan.FromMilliseconds(blagdani_ukupno);
                                    blagdani_ispis = string.Format("{0}:{1}:{2}", ((int)Blagdani_vrijeme.TotalHours), Blagdani_vrijeme.Minutes.ToString("00"), Blagdani_vrijeme.Seconds.ToString("00"));
                                }
                                //another set of departments
                                else if ((rezultat == 0 || rezultat == 1) && item.dan_u_tjednu != "Subota" && BlagdanBolovanje != 1 && (odjelID == 1 || odjelID == 2 || odjelID == 3 || odjelID == 5 || odjelID == 6))
                                {
                                    brojac++;
                                    TimeSpan Blagdan = TimeSpan.FromHours(8);
                                    Ukupuno_sekundi_double += Blagdan.TotalMilliseconds;
                                    Ukupno = TimeSpan.FromMilliseconds(Ukupuno_sekundi_double);
                                    Ukupno_vrijeme = string.Format("{0}:{1}:{2}", ((int)Ukupno.TotalHours), Ukupno.Minutes, Ukupno.Seconds);

                                    blagdani_ukupno += Blagdan.TotalMilliseconds;
                                    Blagdani_vrijeme = TimeSpan.FromMilliseconds(blagdani_ukupno);
                                    blagdani_ispis = string.Format("{0}:{1}:{2}", ((int)Blagdani_vrijeme.TotalHours), Blagdani_vrijeme.Minutes.ToString("00"), Blagdani_vrijeme.Seconds.ToString("00"));
                                }
                                
                                else if ((rezultat == 0 || rezultat == 1) && item.dan_u_tjednu == "Subota" && BlagdanBolovanje != 1 && (odjelID == 4 || odjelID == 7 || odjelID == 8 || odjelID == 9 || odjelID == 10))
                                {
                                    brojac++;
                                    TimeSpan Blagdan = TimeSpan.FromHours(5);
                                    Ukupuno_sekundi_double += Blagdan.TotalMilliseconds;
                                    Ukupno = TimeSpan.FromMilliseconds(Ukupuno_sekundi_double);
                                    Ukupno_vrijeme = string.Format("{0}:{1}:{2}", ((int)Ukupno.TotalHours), Ukupno.Minutes, Ukupno.Seconds);

                                    blagdani_ukupno += Blagdan.TotalMilliseconds;
                                    Blagdani_vrijeme = TimeSpan.FromMilliseconds(blagdani_ukupno);
                                    blagdani_ispis = string.Format("{0}:{1}:{2}", ((int)Blagdani_vrijeme.TotalHours), Blagdani_vrijeme.Minutes.ToString("00"), Blagdani_vrijeme.Seconds.ToString("00"));

                                }
                            }
                        }
                        if (brojac == 0) //if person doesnt have a "right" to have that feast day on his summ
                        {
                            blagdani_ispis = string.Format("00:00:00"); 
                        }
                        brojac = 0; //reset the counter

                        Ukupno = TimeSpan.FromMilliseconds(Ukupuno_sekundi_double); //summ becomes what it was before feast day calculation

The last calculation I make is average worktime:

#region Izracun prosjeka
                        //gets number of working hours for that month
                        komanda = "begin;select sati_rada from radni_sati where zaposlenik_id=@zaposlenik_id " +
                                  " and (napomena='' or napomena is null) and extract(month from radni_sati.datum)=@mjesec_broj and extract(year from radni_sati.datum)=@godina" +
                                  " and sati_rada is not null;commit;";
                        listaParametara.Add(new NpgsqlParameter { ParameterName = "@zaposlenik_id", Value = dt.Rows[i][0] });
                        listaParametara.Add(new NpgsqlParameter { ParameterName = "@mjesec_broj", Value = mjesec_broj });
                        listaParametara.Add(new NpgsqlParameter { ParameterName = "@godina", Value = godina });
                        DataTable SatiRadaBezNapomene = instanca.FillDataTable(komanda, CommandType.Text, listaParametara);
                        listaParametara.Clear();

                        double prosjek = 0;
                        for (int x = 0; x < UkupnoSatiQuery.Rows.Count; x++)
                        {
                            //calculate department_id
                            komanda = "begin;select odjel_id from zaposlenici where zaposlenik_id=@zaposlenik_id;commit;";
                            listaParametara.Add(new NpgsqlParameter { ParameterName = "@zaposlenik_id", Value = dt.Rows[i][0] });
                            int odjel_id = instanca.ExecuteScalar<int>(komanda, CommandType.Text, listaParametara);
                            listaParametara.Clear();

                            if (SatiRadaBezNapomene.Rows.Count > 0) //if that person even has worktime in this month
                            {
                                //depending on the deparment_id
                                if (odjel_id == 1 || odjel_id == 2 || odjel_id == 3 || odjel_id == 5 || odjel_id == 6)
                                {
                                    //redovi=number of rows(days) person has been working + number of holidays +number of sickdays
                                    prosjek = Ukupno.TotalMilliseconds / (redovi + iskoristeni_godisnji + iskoristeno_bolovanje);
                                    upisProsjeka = TimeSpan.FromMilliseconds(prosjek).ToString(@"hh\:mm\:ss");

                                }
                                else if (odjel_id == 4 || odjel_id == 7 || odjel_id == 8 || odjel_id == 9 || odjel_id == 10)
                                {
                                    prosjek = Ukupno.TotalMilliseconds / (redovi + iskoristeni_godisnji + iskoristeno_bolovanje);
                                    upisProsjeka = TimeSpan.FromMilliseconds(prosjek).ToString(@"hh\:mm\:ss");
                                }


                            }
                        }

After all the calculations I fill the datagridview:

                            Ukupno_vrijeme = string.Format("{0}:{1}:{2}", ((int)Ukupno.TotalHours), Ukupno.Minutes, Ukupno.Seconds);
                        DataGridViewRow row = new DataGridViewRow();
                        row.CreateCells(izvjestaj_tablica);
                        row.Cells[0].Value = dt.Rows[i][0]; //ID
                        row.Cells[1].Value = dt.Rows[i][1]; //name
                        row.Cells[2].Value = dt.Rows[i][2]; //surname
                        row.Cells[3].Value = dt.Rows[i][3]; //deparment_id
                        row.Cells[4].Value = suma; //working hours
                        row.Cells[5].Value = upisProsjeka; //average worktime
                        row.Cells[6].Value = redovi; //days of work
                        row.Cells[7].Value = bolovanje_vrijeme;    //sick days
                        row.Cells[8].Value = godisnji_vrijeme; //holidays
                        row.Cells[9].Value = blagdani_ispis; //feast days
                        row.Cells[10].Value = Ukupno_vrijeme; //total

Thats how my monthly report looks like. I didnt include some basic stuff like creating a datagridview, filling it with columns and their names, formating them and some other properties for the datagridview.

P.S. If you find some part of the code thats unclear, feel free to ask for editing, its a bunch of code and I commented it on a fast paste so maybe I didnt explain everything as I should.