0

I am accessing a database with c#. Now I have to make some calculations with data that I get from some tables and write it into other existing tables. This works quite good in most cases, but for complex operations it takes a huge amount of time. Now I want to know what would be good practice to speed up my querys and get to my results. Here is what I do:

  1. I get a data table that contains 3 values (lom(unique id), laktanfang, laktende) that contains about 700 rows.
  2. For each row in this table I do a query from another table. This results in another data table containing 2 values (lom(unique id), behanddatum)
  3. Now I check if the the value of behanddatum is in between laktanfang and laktende --> yes: Add the row to the data table that gets returned by my function --> no: go on
  4. In the end I have to get the number of positive results from my data table

Here is the code I currently use. I hope it's not too confusing.

public DataTable HoleAbgeschlosseneLaktationenMitDiagnosen(DateTime daAnfang, DateTime daEnde, string[] stDiagnosen = null)
    {            
        DataTable dtRet = new DataTable();
        dtRet.Columns.Add("lom", typeof(string));
        dtRet.Columns.Add("laktanfang", typeof(DateTime));
        dtRet.Columns.Add("laktende", typeof(DateTime));

        DataTable dtAbgänge = HoleAbgängeVonEinzeltierZugang(daEnde, daAnfang);
        //Abgeschlossene Laktationen für abgegegangene Tiere
        foreach (DataRow dr in dtAbgänge.Rows)
        {
            if (dr != null)
            {
                DateTime daAbgangsdatum = dr.Field<DateTime>("abgangsdatum");
                string stLom = dr.Field<string>("lom");
                DataTable dtKalbungVorAbgang = HoleLetzteKalbungFuerTier(stLom, daAbgangsdatum);

                if (dtKalbungVorAbgang.Rows.Count > 0 && !dtKalbungVorAbgang.Rows[0].IsNull("kalbedatum"))
                {
                    DateTime daKalbedatum = (DateTime)dtKalbungVorAbgang.Rows[0]["kalbedatum"];
                    int inLaktation = (int)dtKalbungVorAbgang.Rows[0]["laktation"];

                    if (PrüfeObDiagnoseInZeitraumAufgetreten(stLom, stDiagnosen, daKalbedatum, daAbgangsdatum) || stDiagnosen == null)
                    {
                        DataRow drLaktAbgang = dtRet.NewRow();
                        drLaktAbgang["lom"] = stLom;
                        drLaktAbgang["laktanfang"] = daKalbedatum;
                        drLaktAbgang["laktende"] = daAbgangsdatum;
                        dtRet.Rows.Add(drLaktAbgang);
                    }

                    if (daKalbedatum >= daAnfang && inLaktation > 1)
                    {
                        DataTable dtVorherigeKalbung = HoleLetzteKalbungFuerTier(stLom, daKalbedatum.AddDays(-1));
                        DateTime daVorhKalbung = (DateTime)dtVorherigeKalbung.Rows[0]["kalbedatum"];

                        if (dtVorherigeKalbung.Rows.Count > 0 && !dtVorherigeKalbung.Rows[0].IsNull("kalbedatum"))
                        {
                            if (PrüfeObDiagnoseInZeitraumAufgetreten(stLom, stDiagnosen, daKalbedatum, daAbgangsdatum) || stDiagnosen == null)
                            {
                                DataRow drLaktVorhKalbung = dtRet.NewRow();
                                drLaktVorhKalbung["lom"] = stLom;
                                drLaktVorhKalbung["laktanfang"] = daVorhKalbung;
                                drLaktVorhKalbung["laktende"] = daKalbedatum;
                                dtRet.Rows.Add(drLaktVorhKalbung);
                            }
                        }
                    }
                }
            }                
        }          

        DataTable dtKalbungen = HoleKalbungenFürLebendTiere(daEnde, daAnfang);
        //Abgeschlossene Laktationen für lebende Tiere
        foreach (DataRow dr in dtKalbungen.Rows)
        {
            DateTime daKalbedatumLetzte = dr.Field<DateTime>("kalbedatum");
            string stLom = dr.Field<string>("lom");
            int inLaktation = dr.Field<int>("laktation");

            if (inLaktation > 1)
            {
                DataTable dtKalbungVorErster = HoleLetzteKalbungFuerTier(stLom, daKalbedatumLetzte.AddDays(-1));

                if (!dtKalbungVorErster.Rows[0].IsNull("kalbedatum"))
                {
                    DateTime daKalbedatum = (DateTime)dtKalbungVorErster.Rows[0]["kalbedatum"];

                    if (PrüfeObDiagnoseInZeitraumAufgetreten(stLom, stDiagnosen, daKalbedatum, daKalbedatumLetzte) || stDiagnosen == null)
                    {
                        DataRow drLaktKalbung = dtRet.NewRow();
                        drLaktKalbung["lom"] = stLom;
                        drLaktKalbung["laktanfang"] = daKalbedatum;
                        drLaktKalbung["laktende"] = daKalbedatumLetzte;
                        dtRet.Rows.Add(drLaktKalbung);
                    }                      

                    inLaktation = (int)dtKalbungVorErster.Rows[0]["laktation"];

                    if (daKalbedatum >= daAnfang && inLaktation > 1)
                    {
                        DataTable dtVorherigeKalbung = HoleLetzteKalbungFuerTier(stLom, daKalbedatum.AddDays(-1));

                        if (dtVorherigeKalbung.Rows.Count > 0 && !dtVorherigeKalbung.Rows[0].IsNull("kalbedatum"))
                        {
                            DateTime daVorhKalbung = (DateTime)dtVorherigeKalbung.Rows[0]["kalbedatum"];

                            if (PrüfeObDiagnoseInZeitraumAufgetreten(stLom, stDiagnosen, daVorhKalbung, daKalbedatum) || stDiagnosen == null)
                            {
                                DataRow drLaktVorhKalbung = dtRet.NewRow();
                                drLaktVorhKalbung["lom"] = stLom;
                                drLaktVorhKalbung["laktanfang"] = daVorhKalbung;
                                drLaktVorhKalbung["laktende"] = daKalbedatum;
                                dtRet.Rows.Add(drLaktVorhKalbung);
                            }                                
                        }
                    }
                }
            }                
        }

        return dtRet;
    }

    private bool PrüfeObDiagnoseInZeitraumAufgetreten(string stLom, string[] stDiagnosen, DateTime daAnfang, DateTime daEnde)
    {
        SqlCommand cmd = new SqlCommand();
        DataTable dtDiagnosenGefunden = new DataTable();

        cmd.CommandText = "SELECT diagnose " +
                          "FROM b_milch_hms_diagnose " +
                          "WHERE lom=@lom AND behanddatum >= @datumanfang AND behanddatum <= @datumende";

        if (stDiagnosen != null)
        {
            int i = 0;

            foreach (string st in stDiagnosen)
            {
                if (st != "")
                {
                    if (i == 0)
                        cmd.CommandText += " AND diagnose LIKE @gesuchte_diagnose" + i;
                    else
                        cmd.CommandText += " OR diagnose LIKE @gesuchte_diagnose" + i;
                    cmd.Parameters.AddWithValue("@gesuchte_diagnose" + i, st + "%");
                }

                i++;
            }
        }

        cmd.Parameters.AddWithValue("@lom", stLom);
        cmd.Parameters.AddWithValue("@datumanfang", daAnfang);
        cmd.Parameters.AddWithValue("@datumende", daEnde);

        dtDiagnosenGefunden = w_milch.FühreSqlAus(cmd);
        if (dtDiagnosenGefunden.Rows.Count > 0 && !dtDiagnosenGefunden.Rows[0].IsNull("diagnose"))
            return true;

        return false;

    }

I hope you can help me to improve this function to work more efficient or at least give me some hints.

Thanks in advance

2 Answers 2

1

You have created a N+1 problem. One way to solve this would be to change HoleAbgängeVonEinzeltierZugang so that it joins in the data you need from the b_milch_hms_diagnose table.

Sign up to request clarification or add additional context in comments.

Comments

1

If you are using .NET 4.0, you can also try to use parallel foreach and see the impact it has on the loop execution time. (This is a more general advice you could apply to many examples)

    _dtAbgänge.Rows.AsParallel().ForEach(dr=>
                                              {
                                                  //do work
                                              });        

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.