checkedListBox winforms// SQL

0

Cześć,
tworzę mały program w którym będę wyświtalał sumowane dane poszczególnych urzadzeń. do wyboru urzadzeń używam checkedListBox a do wyświetlania danych DatagridViiew1. Chcę mieć możliwość wyboru w checkedListBox1 jedno urządzenie lub kilka, checkedListBox1 wypełniam automatycznie łacząc się z bazą danych:

      SqlCommand cmd = new SqlCommand("SELECT [VehicleId] ,[RegNo]  FROM[TMSCLIENT4].[dbo].[Vehicle]", con);
            SqlDataAdapter sda = new SqlDataAdapter(cmd);
            DataTable dt = new DataTable();
            sda.Fill(dt);
            checkedListBox1.Items.Add("");
            for (int i = 0; i < dt.Rows.Count; i++)
            {
                checkedListBox1.Items.Add(dt.Rows[i]["RegNo"].ToString());
            }

Teraz chcę aby w zależności co wybierze użytkownik (1,2 czy więcej urzadzeń) wyświetliły sie dane poszczególnych urządzeń w DataGridView, dla zapytania z SQLa

   SELECT
   CAST(SUM(Weight) AS DECIMAL(10, 2)) AS 'Produkacja [t]', 
   VehicleId
   FROM[TMSCLIENT4].[dbo].[vwConveyorScaleMinute] 
   WHERE VehicleId  IN('1','2','4','7') 
   AND WorkDateTime BETWEEN '2021-09-01 01:00:00.000' AND '2021-09-01 23:00:00.000'   
   group by VehicleId

Gdzie '1','2','4','7' -- to właśnie urządzenia z checkedListBox1,,kod w c# wygląda tak:

   con.Open();
                SqlDataAdapter sqlData = new SqlDataAdapter
            ("SELECT CAST(SUM(Weight) AS DECIMAL(10, 2)) AS 'Produkacja [t]', VehicleId FROM[TMSCLIENT4].[dbo].[vwConveyorScaleMinute]  WHERE VehicleId  IN('" + checkedListBox1.Items + "','') AND WorkDateTime BETWEEN '2021-01-01 01:00:00.000' AND '2021-02-01 01:00:00.000'   group by VehicleId", con);
                DataTable dtbl = new DataTable();
                sqlData.Fill(dtbl);
                dataGridView1.DataSource = dtbl;
                con.Close();

Próbowałem przez checkedListBox1.Items i różnych innych i nie mogę sobie z tym poradzić .

1

Nie jestem pewien czy dobrze rozumiem idee, ale wydaje mi się ze idziesz na skroty podlaczajac od razu wynik zapytania do 'checkedListBox'. W Podobnych przypadkach zawsze robilem modele do tego co odczytywalem z bazy i kolekcje tych modeli byly zrodlem danych dla kontrolek na UI.

Proponuje Ci zrobic cos takiego:

  1. zdefiniuj klase obiektu ktory bedzie odwzorowywal jeden rekord z wyniku zapytania , koniecznie musi miec jedna wlasciwosc typu bool /bedzie checkiem na 'checkedListBox'/
  2. wynik pierwszego zapytania zapisz do kolekcji obiektow typu ktory zdefiniujesz w pkt.1.
  3. ustaw ta kolekcje jako DataSource dla 'checkedListBox'
  4. zaznaczajac 'check' obiektu na 'checkedListBox' zaznaczasz urzadzenia w swojej kolekcji ktore chcesz sumowac
  5. nastepwnie gdy bedziesz chcial juz sumowac, /czy przekazac zaznaczone urzadzenia do zapytania ktore zwroci sume/, przelec w petli po kolekcji swoich obiektow, i z kazdego z nich ktory ma 'check' ustawiony na true pobierz 'id' i taka pule 'id' przekaz do drugiego zapytania i wykonaj.

oczywiscie bedzie pare niuansow z odswiezaniem i synchronizacja tego co w modelu i tego co wyswietlane na UI ale to juz bedzie z gorki.

PS. Mi zawsze najlatwiej jest najpierw wykonywac takie zapytania z uzyciem samego modelu, bez zadnego wyswietlania na UI po prostu debugujac podgladam co w jakim momencie jaki ma stan. podpiecie do UI bedzie wtedy z gorki.

1

Tyle co mogę/umiem to poniżej, zalozylem ze wszystkie wlasciwosci modelu są 'string' ale dla zobrazowania o co mi chodzilo powinno wystarczyc i z latwoscia bedziesz mogl je dostosowac do swojego przykladu.

W pierwszym kroku definiuje to co zwróci zapytanie: "SELECT [VehicleId] ,[RegNo] FROM[TMSCLIENT4].[dbo].[Vehicle]"

    public class ObiektJeden
    {
        public string VehicleId { get; set; }   
        public string RegNo { get; set; }

        public override string ToString()
        {
            return $"{VehicleId}_{RegNo}";
        }
    }

Nastepnie tworze kolekcje obiektow typu 'ObiektJeden' i zapelniam ją wynikami zapytania tak:

            List<ObiektJeden> kolekcjaObiektyJeden = new List<ObiektJeden>();

            string queryString = "SELECT [VehicleId] ,[RegNo]  FROM[TMSCLIENT4].[dbo].[Vehicle]";

            using (SqlConnection connection = new SqlConnection(connectionString))
            {
                SqlCommand command = new SqlCommand(queryString, connection);
                connection.Open();
                using (SqlDataReader reader = command.ExecuteReader())
                {
                    while (reader.Read())
                        kolekcjaObiektyJeden.Add(new ObiektJeden() { VehicleId = reader[0].ToString(), RegNo = reader[1].ToString() });
                }
            }

w ten sposob laduje je do kontrolki 'ChceckedListBox'.

            foreach (var item in kolekcjaObiektyJeden)
                checkedListBox1.Items.Add(item);

teraz aby pobrac 'Id' obiektow zaznaczonych w 'CheckedListBox' ktore beda potrzebne do uzupelnienia zapytania SQL nr.2 robie tak:

            List<string> listaZaznaczonychID = new List<string>();

            foreach (var item in checkedListBox1.CheckedItems)
            {
                var obiekt = (ObiektJeden)item;
                listaZaznaczonychID.Add(obiekt.VehicleId);                
            }

i na koniec "składam" zapytanie nr.2 zawierajace liste pobranych "Id" zaznaczonych maszyn w CheckedListBox.

            StringBuilder sb = new StringBuilder();
            foreach (var item in listaZaznaczonychID)
                sb.Append($"'{item}', ");

            string StringZaznaczonych = sb.ToString().Substring(0, sb.Length - 2);

            string zapytanieSQL2 = $"SELECT" + 
                                    "CAST(SUM(Weight) AS DECIMAL(10, 2)) AS 'Produkacja [t]', " +
                                    "VehicleId" +
                                    "FROM[TMSCLIENT4].[dbo].[vwConveyorScaleMinute]" +
                                    $"WHERE VehicleId  IN({StringZaznaczonych})" + 
                                    "AND WorkDateTime BETWEEN '2021-09-01 01:00:00.000' AND '2021-09-01 23:00:00.000'" +
                                    "group by VehicleId";

Teraz zostaje analogicznie jak wczesniej:

  1. zdefiniowac "obiektTypu2" ktory bedzie wynikiem zapytania "zapytanieSQL2"
  2. odczytac zapytanie nr2 i zapisac wyniki do kolekcji List<obiektTypu2>
  3. ustawic kolekcje List<okiektTypu2> jako DataSource kontrolki DataGridView

1 użytkowników online, w tym zalogowanych: 0, gości: 1