Access, C#: Получить список таблиц в Combobox и по нему загружать данные

Интересная вчера попалась задача. Есть стандартная база данных для MS Access. «Борей» называется. Что это может значить мне так и не понятно. Нужно написать программу которая загружает список таблиц в combobox, а потом по выбору из него таблицы загружает содержимое в DataGridView. Язык реализации C#.

Голову поломал, ушло 7 часов, но сделал. Я буду рад, если кому пригодится.

Интерфейс получился такой:

Интерфейс программы

По первой кнопке загружаем список таблиц из базы в combobox, вторая загружает данные из выбранной в DataGridView.

Для работы с базой мне потребовалась следующая сборка:

using System.Data.OleDb;

А далее код, который привязан к первой кнопке:

comboBox1.Items.Clear();
            OleDbConnection dbCon = new OleDbConnection(
             @"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=Борей.mdb");
            dbCon.Open();
                DataTable tbls=dbCon.GetSchema("Tables",new string[] { null, null, null, "TABLE" }); //список всех таблиц
                foreach (DataRow row in tbls.Rows)
                {
                    string TableName = row["TABLE_NAME"].ToString();
                    comboBox1.Items.Add(TableName);
                }
             dbCon.Close();

Код для получения таблиц взят на форуме, а потом изменен.

Первое, что делается — очистка списка в ComboBox, что бы не загрузить список таблиц поверх. Далее, создается соединение с базой данных используя OleDB. Получаем схему и проходя по ней получаем список таблиц. Последней строкой закрываем соединение.

Вторая кнопка:

OleDbConnection dbCon = new OleDbConnection(
             @"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=Борей.mdb");
            dbCon.Open();
            OleDbDataAdapter dbAdapter1 = new OleDbDataAdapter(@"SELECT " + comboBox1.SelectedItem + @".* FROM " + comboBox1.SelectedItem, dbCon);
            DataTable dataTable = new DataTable();
            dbAdapter1.Fill(dataTable);
            dataGridView1.DataSource = dataTable;
            dbCon.Close();

Здесь, тоже самое. Создаем подключение открываем соединение, Создаем новый адаптер с запросом к нашей базе такого вида:

SELECT  .* FROM

и выполняем этот запрос. Создаем новую таблицу данных. Заполняем ее данными полученными от запроса. Связываем Таблицу с DataGridView и закрываем соединение. Данные загружены:

Данные из таблицы загружены

Добавлено:

Немного модифицировал код, но суть осталась та же. Весь проект теперь доступен тут: AccessDB
О тестовой базе данных написано тут

UPD: Как получить список полей таблицы?

28 Responses

  1. Жека 24.07.2012 / 18:56

    Называется «Борей», потому что неправильно перевели «Northwind.mdb».
    А за толковое объяснение спасибо, как раз для новичков.

  2. Сергей 15.09.2012 / 20:07

    Спасибо, большущее! Можно использовать как учебное пособие. Попробовал сам и все с первого раза все заработало. Побольше бы таких источников!

  3. Евгений 08.11.2012 / 01:03

    Спасибо большое!!! Очень понятно всё написано!!! Просто слов нет, чтобы выразить благодарность Вам! Очень большое спасибо!
    Перерыл много сайтов и везде всё было замудрено, тут же всё просто и понятно.

    • Pyatnitsev 08.11.2012 / 07:47

      Спасибо за добрые слова!
      PS: Если слов не хватает, но хочется сделать приятно, есть Яндекс.Деньги: 41001241821675 :)

  4. Александр 17.11.2012 / 03:30

    Добрый автор, не подскажешь как получить имена всех столбцов из таблицы?

  5. Александр 18.02.2013 / 00:53

    Подскажите а как можно один элемент таблицы вывести допустим как с элемента dataGridView

     string s=dataGridView1.Rows[0].Cells[0].Value.ToString(); 

    только вместо dataGridView использовать допустим dataTable или как-нибудь еще
    так как в dataGridView можно отображать не все столбцы на а в коде допустим нужно будет использовать не отображённый столбец.

    • Pyatnitsev 18.02.2013 / 01:00

      Не совсем понимаю вопрос.
      Вам нужно использовать другой контролл для отображения на форме?
      Или нужно как-то обращаться из кода? пишите на почту, постараюсь помочь: [email protected]

  6. Денис 03.03.2013 / 11:34

    Добрый день! Подскажите пожалуйста, как согласно кода выше получить значения выбранного поля? К примеру:

    Имя поля базы данных «Название» из него получить все данные не прибегая к DGV?

  7. Олег 15.03.2013 / 19:53

    Подскажите вот, что у меня есть две таблицы Regions и таблица MembersInfo, задача вот в чем при добавления нового клиента нужно указать регион , как программно свзять СomboBox, из таблицей Regions, что бы получить список регионов, и при выборе данного региона в таблицю MembersInfo записывался его id???

    • Pyatnitsev 15.03.2013 / 23:51

      Создайте 2 класса: в первом храните всю информацию из таблицы, в другом экземпляры первого класса.
      Дальше из второго (из коллекции) грузите данные на форму. Ну и при выборе обращайтесь к списку, а внутри него просите id. понятно?

      • Олег 16.03.2013 / 03:30

        Простите, а можно код….я уже весь инет облазил, и толковое не чего не нашел?. Очень нужно

  8. Олег 16.03.2013 / 04:00

    Вот так я заполнил СomboBox на форме MembersInfo:

        private void MembersInfo_Load(object sender, EventArgs e)
            {
                DataSet ds = new DataSet();
                com = new OleDbCommand("Select*from Regions", con);
                adp = new OleDbDataAdapter(com);
                adp.Fill(ds);
                cbx_IdRegion.DataSource = ds.Tables[0];
                cbx_IdRegion.DisplayMember = "RegionName";
                cbx_IdRegion.ValueMember = "Region_ID";
            }
    

    Теперь у меня есть метод добавления новой записи в таблицу MembersInfo

    public void AddRecord()
            {
                try
                {
                    if (MessageBox.Show("Ви дійсно хочете додати запис?", "Увага", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes)
                    {
                        DataTable dt = new DataTable();
                        OleDbCommand com = new OleDbCommand("Insert INTO                  MembersInfo (MI_ID, Group_ID, Region_ID)VALUES('" + txbx_MI_ID + "', '" + txbx_Group_ID + "' , '" + cbx_IdRegion + "')", con);
                        OleDbDataAdapter adp = new OleDbDataAdapter(com);
                        adp.Fill(dt);
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
            }
    

    Ну id выбранного из СomboBox региона в таблицу не в носится, выдает сообщения: Несоответствие типов данных в выражении условия отбора.
    Пожалуйста посмотрите мой код!

  9. Алексей 28.04.2014 / 01:58

    Подскажите, В своем проекте я использовал этот способ все отлично работает но как реализовать сохранения изменений в таблице выбранной в combobox через кнопку.????????

    • Pyatnitsev 28.04.2014 / 12:14

      Добрый день!

      Что именно вы хотите сделать? Насколько я понял:
      1. Загрузить данные
      2. Отредактировать
      3. Сохранить их в БД.

      В чем именно у вас возникает сложность?

      Если вы не знаете, как сделать запрос, то у вас есть метод button2_Click:

      OleDbConnection dbCon = new OleDbConnection(
       @"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + openFileDialog1.FileName);
                      dbCon.Open();
                      OleDbDataAdapter dbAdapter1 = new OleDbDataAdapter(@"SELECT * FROM [" + comboBox1.SelectedItem + "]", dbCon);
                      DataTable dataTable = new DataTable();
                      dbAdapter1.Fill(dataTable);
                      dataGridView1.DataSource = dataTable;
                      dbCon.Close();
      

      В нем я собираю строку соединения (DataProvider + то, что выбрал пользователь в Combobox). Открываю соединение, делаю запрос для выборки всех в адаптер — это самое интересное. Дальше выкидываю это на форму. Для UPDATE и INSERT Adapter не нужен.

      Можно написать примерно такой код:

      OleDbConnection dbCon = new OleDbConnection(
       @"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + openFileDialog1.FileName);
                      dbCon.Open();
      string query = "UPDATE [Contact] SET [FirstName] = ? [LastName] = ?, [MobileNumber] = ? WHERE [Id] = ?"
       OleDbCommand cmd = new OleDbCommand(query, db) { CommandType = CommandType.Text };
              cmd.Parameters.AddWithValue("@Id", contact.Id);
              cmd.Parameters.AddWithValue("@FirstName", contact.FirstName);
              cmd.Parameters.AddWithValue("@LastName", contact.LastName);
              cmd.Parameters.AddWithValue("@MobileNumber", contact.MobileNumber);
      int rowsAffected = cmd.ExecuteNonQuery();
      
      dbCon.Close();
                      
      

      Похожий пример я нашел на stackoverflow.com. Разница у вас в том, что при динамической работе с БД вам придется собирать строку для UPDATE и соответственно подбирать параметры.

      Я ответил на вопрос?

  10. Алексей 28.04.2014 / 19:57

    Если можно для ДУРАКОВ). на примере вашей программы что именно писать в update.
    Знакомлюсь с програмированием в целом 2 неделю многое дается с трудом в понимании.

    • Pyatnitsev 28.04.2014 / 23:24

      Давайте тогда так…
      Почитайте сначала про SQL. Есть неплохая книжка для начинающих.

      Алан Бьюли, Изучаем SQL Там само описание языка SQL, без привязке к конкретной реализации.

      Дальше, если вам нужно работать именно в MDB можно читать MSDN, гуглить по поводу OleDb.

      А насчет примера. Что именно вы бы хотели увидеть?

  11. Алексей 29.04.2014 / 00:26

    Спасибо за книжку неприменимо почитаю, но сейчас времени на этом совсем нету нужно сдавать диплом. для моей специальности (прикладная информатика в экономике) достаточно бы было просто создать бд в акцесе и все но я решил усложнить себе жизнь и добавить чуток программирования. Все по сути готова кроме этой кнопки для внесения изменений в открытой таблице.

           
     private void button4_Click(object sender, EventArgs e)
            {
                OleDbConnection dbload = new OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;data source=D:\\111111111111111\\Учет премии.accdb");
                dbload.Open();
                OleDbDataAdapter dbAdapter1 = new OleDbDataAdapter(@"SELECT " + comboBox1.SelectedItem + @".* FROM " + comboBox1.SelectedItem, dbload);
                DataTable dataTable = new DataTable();
                dbAdapter1.Update(учет_премииDataSet.Tables[dataTable]);
              
                dbload.Close();
                
            }
    

    или так

    dbAdapter1.Update(dataTable);
    

    в первом случае ошибка во втором компилируеться но не работает )

  12. Екатерина 02.05.2014 / 22:10

    Доброго дня! Спасибо за статью) Очень помогла) Только есть вопрос: как разбить таблицы с БД по разным comboBox-ам, а именно выборка таблиц для разных comboBox за условием? Например: в comboBox(Салаты) выводить только таблицы с рецептами салатов и т.д. И как уже в dataGridView вывести не все поля?
    Спасибо))))

    • Pyatnitsev 03.05.2014 / 00:17

      Здравствуйте, Екатерина!

      Что бы выбрать в разные комбобоксы нужно написать различные SQL-запросы (по одному для каждой категории). Даже не совсем SQL-запросы.

      Выборка таблиц происходит тут:

      OleDbConnection dbCon = new OleDbConnection(
                  @"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + openFileDialog1.FileName);
                      dbCon.Open();
                      DataTable tbls = dbCon.GetSchema("Tables", new string[] { null, null, null, "TABLE" }); //список всех таблиц
                      foreach (DataRow row in tbls.Rows)
                      {
                          string TableName = row["TABLE_NAME"].ToString();
                          comboBox1.Items.Add(TableName);
                      };
                      dbCon.Close();    
      

      Соответственно вам нужен метод GetSchema(). Почитать кратко о нем можно на MSDN

      Например, что бы выбрать таблицу с определенным именем можно сделать так:

      DataTable tbls = dbCon.GetSchema("Tables", new string[] { null, null, "Заказы", "TABLE", }); //Получить таблицу "Заказы"
      

      Вторая часть вопроса касается dataGridView.

      Здесь уже простые SQL-запросы. Для каждого случая их придется написать отдельно. Рассмотрите метод, где у меня выполняется запрос:

       if (comboBox1.SelectedIndex != -1)
                  {
                      OleDbConnection dbCon = new OleDbConnection(
       @"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + openFileDialog1.FileName);
                      dbCon.Open();
                      OleDbDataAdapter dbAdapter1 = new OleDbDataAdapter(@"SELECT * FROM " + comboBox1.SelectedItem, dbCon);
                      DataTable dataTable = new DataTable();
                      dbAdapter1.Fill(dataTable);
                      dataGridView1.DataSource = dataTable;
                      dbCon.Close();
                  }
                  else
                  {
                      MessageBox.Show("Не выбрана таблица для запроса");
                  }
      

      Вот это сам SQL-запрос (он собирается по кусочкам):

      "SELECT * FROM " + comboBox1.SelectedItem
      

      Для того, что бы выбрать отдельные поля нужно его просто изменить. Например, для таблицы клиенты я сделал так:

      "SELECT [КодЗаказа],[КодКлиента] FROM " + comboBox1.SelectedItem
      

      Этот запрос выбирает только КодЗаказа и КодКлиента.
      Приложение будет выглядеть так:
      Приложение с измененным запросом

  13. Екатерина 03.05.2014 / 02:15

    Огромное спасибо!) (Как могу отблагодарить?)
    Все работает, только кода получилось многовато) Думаю и так сойдет!)
    Вы очень толково объясняете, что добавляет вам кучу плюсов!) Думаю я обращусь еще не раз именно к вам)

  14. Денис 21.05.2014 / 01:54

    есть база данных access и среда программирования C#
    есть несколько связанных таблиц
    эти таблицы нужно вывести на форму в таблицы и иметь возможность выбрав что-то в одной таблице — получить из-за связи нужное значение в другой

    можете написать, как эти сделать?

    • Pyatnitsev 21.05.2014 / 23:04

      Насколько я понимаю, ваша проблема решается пересечением таблиц.
      Рекомендую почитать по поводу Joins / inner join / left join и так далее.

      Пример? Я пошел на TechNet и вот что там взял:

      USE AdventureWorks2008R2;
      GO
      SELECT *
      FROM HumanResources.Employee AS e
          INNER JOIN Person.Person AS p
          ON e.BusinessEntityID = p.BusinessEntityID
      ORDER BY p.LastName
      

      Примерно так оно и выглядит.

      • Денис 21.05.2014 / 23:51

        я не очень хорошо понял данный пример, да и с sql у меня проблемы, вы можете скинуть рабочий пример?

        • Pyatnitsev 21.05.2014 / 23:58

          К сожалению, сейчас слишком мало времени.

          Вы можете посмотреть этот комментарий. Я там говорю про SQL-запросы.

          Учите SQL. Вам это поможет.

  15. Серега 17.06.2014 / 21:21

    Автор, ты просто космос!!!!!!!!!!
    я везде именно это и искал, спасибо тебе огромное!!!

Добавить комментарий