0

C# でデータベースにアクセスしています。ここで、いくつかのテーブルから取得したデータを使用して計算を行い、それを他の既存のテーブルに書き込む必要があります。これはほとんどの場合にうまく機能しますが、複雑な操作の場合は膨大な時間がかかります。ここで、クエリを高速化し、結果を取得するための良い方法を知りたいと思います。これが私がすることです:

  1. 約 700 行を含む 3 つの値 (lom(unique id)、laktanfang、laktende) を含むデータ テーブルを取得します。
  2. このテーブルの各行に対して、別のテーブルからクエリを実行します。これにより、2 つの値 (lom(unique id)、behanddatum) を含む別のデータ テーブルが作成されます。
  3. ここで、behanddatum の値が laktanfang と laktende の間にあるかどうかを確認します --> はい: 関数によって返されるデータ テーブルに行を追加します --> いいえ: 続行します
  4. 最後に、データ テーブルから肯定的な結果の数を取得する必要があります。

ここに私が現在使用しているコードがあります。あまり混乱しないことを願っています。

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;

    }

この機能を改善してより効率的に動作させるか、少なくともいくつかのヒントを教えていただければ幸いです。

前もって感謝します

4

2 に答える 2

1

.NET 4.0を使用している場合は、並列foreachを使用して、ループの実行時間に与える影響を確認することもできます。(これは、多くの例に適用できるより一般的なアドバイスです)

    _dtAbgänge.Rows.AsParallel().ForEach(dr=>
                                              {
                                                  //do work
                                              });        
于 2012-11-23T13:30:55.133 に答える
1

N+1問題を作成しました。これを解決する 1 つの方法は、テーブルから必要なデータを 結合HoleAbgängeVonEinzeltierZugangするように変更することです。b_milch_hms_diagnose

于 2012-11-23T13:22:13.873 に答える