Как заполнить сгенерированный столбец в datagridview наиболее эффективным способом? - PullRequest
0 голосов
/ 29 апреля 2020

У меня есть настройка DataGridView в моей программе Winforms с информацией, заполняемой из базы данных.

Я заполнил сетку данных с помощью Select * FROM [Data] следующим кодом:

        private void GetData(string selectCommand)
        {
            try
            {
                // Create a new data adapter based on the specified query.
                dataAdapter = new OleDbDataAdapter(selectCommand, strConn);

                // Create a command builder to generate SQL update, insert, and
                // delete commands based on selectCommand.
                OleDbCommandBuilder commandBuilder = new OleDbCommandBuilder(dataAdapter);

                // Populate a new data table and bind it to the BindingSource.
                DataTable table = new DataTable
                {
                    Locale = CultureInfo.InvariantCulture
                };
                dataAdapter.Fill(table);
                bindingSource1.DataSource = table;

                // Resize the DataGridView columns to fit the newly loaded content.
                LogDataGridView.AutoResizeColumns(
                    DataGridViewAutoSizeColumnsMode.AllCellsExceptHeader);
            }
            catch (OleDbException)
            {

            }
        }

Ответы [ 2 ]

1 голос
/ 29 апреля 2020

Опция 1 :

Если база данных, в которой хранится информация о состоянии, не постоянно обновляется каким-либо другим процессом, вы можете просто указать, что столбец для объединения является частью таблицы во внешней базе данных.

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

Добавьте [;database=Second database Path].[Source Table] AS alias после предложения JOIN, затем продолжайте как обычно.

Например, установите DataGridView.Datasource, указав второй путь к базе данных.

LogDataGridView.DataSource = GetCrossJoinedTable([Second database path]);

Строка подключения Data Source= содержит путь к первой базе данных.
Затем выполните перекрестное соединение двух таблиц в двух базах данных, используя общий ключ, и верните столбец, содержащий информацию о состоянии. из таблицы во второй базе данных (столбец [Order Status], если я правильно прочитал обновленный код).

private DataTable GetCrossJoinedTable(string secondDataBasePath)
{
    var dt = new DataTable("JoinedTable");
    string sql = "SELECT [Data].*, status.[Order Status] " +
                $"FROM [Data] LEFT JOIN [;database={secondDataBasePath}].[Output] AS status " +
                 "ON [Data].[SO nr] = status.[Source No]";
    using (var connection = new OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=firstDatabase.accdb;Persist Security Info=false;"))
    using (var command = new OleDbCommand(sql, connection)) {
        connection.Open();
        var reader = command.ExecuteReader();
        dt.Load(reader);
        return dt;
    }
}

Опция 2 :
Запросить первую базу данных, добавить столбец состояния, обновить информацию о состоянии из второй базы данных, а затем опросить новую информацию о состоянии с помощью таймера.

Вы можете позвонить LogDataGridView.DataSource = GetMainTableData(), чтобы установить источник данных. Он также загрузит информацию о состоянии из второй базы данных.

Затем таймер будет опрашивать только вторую базу данных, чтобы проверить, изменился ли [Order Status] соответствующего столбца [SO nr] в DataTable.
Когда DataTable (здесь, поле с именем * 1034) *) обновляется, ваш DataGraidView немедленно отразит изменение.

  • Если данные можно редактировать, таймер должен пропустить обновление, если IsCurrentCellInEditMode вернет true (прочитайте заметки там о CheckBoxColumns) или остановится, пока ячейка в режиме редактирования ( CellBeginEdit событие) и возобновляется при выходе ячейки из режима редактирования ( CellEndEdit событие).
  • Не забудьте останавливать и утилизировать таймер при закрытии формы (событие Form.FormClosing).

Если вам не нужен таймер для опроса информации о состоянии, просто звоните UpdateStatusInfo() всякий раз, когда вам нужно обновить DGV.

System.Windows.Forms.Timer sqlTimer = null;
DataTable mainDT = new DataTable("MainTable");

private DataTable GetMainTableData()
{
    string sql = "SELECT * FROM Data";
    using (var connection = new OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=firstDatabase.accdb;Persist Security Info=false;"))
    using (var command = new OleDbCommand(sql, connection)) {
        connection.Open();
        var reader = command.ExecuteReader();
        mainDT.Load(reader);
        mainDT.Columns.Add(new DataColumn() {
            Caption = "Status", ColumnName = "fStatus", DataType = typeof(string), ReadOnly = true
        });
    }
    sqlTimer = new System.Windows.Forms.Timer() { Interval = 5000 };
    sqlTimer.Tick += (s, ev) => { UpdateStatusInfo(mainDT, false); };
    sqlTimer.Start();
    return UpdateStatusInfo(mainDT, true);
}

private DataTable UpdateStatusInfo(DataTable dt, bool returnTable)
{
    string sql = "SELECT Output.[Order Status], Output.[Source No] FROM Output";
    using (var connection = new OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=secondDatabase.accdb;Persist Security Info=false;"))
    using (var command = new OleDbCommand(sql, connection)) {
        connection.Open();
        var reader = command.ExecuteReader();
        dt.Columns["fStatus"].ReadOnly = false;
        while (reader.Read()) {
            dt.Select($"fNumber = {reader["Source No"]}").FirstOrDefault()?
              .SetField("fStatus", reader["Order Status"].ToString());
        }
        dt.Columns["fStatus"].ReadOnly = true;
        return returnTable ? dt : null;
    }
}
0 голосов
/ 29 апреля 2020

Что вы можете сделать:

1 / Вы создаете переменную DataTable из своей таблицы OUTPUT (например, OutputDataTable)

2 / В вашем методе private void GetData(string selectCommand), перед настройкой источника данных (bindingSource1.DataSource = table;), вы описываете событие RowsAdded (dataGridView1.RowsAdded += this.DataGridView1_RowsAdded;). Если вы делаете что-то вроде:

    private void DataGridView1_RowsAdded(object sender, DataGridViewRowsAddedEventArgs e)
    {
        string valueToFind = dataGridView1[dataGridView1.Columns["SO nr"].Index, e.RowIndex].Value.ToString();
        var row = OutputDataTable.Select($"Source No" = '{valueToFind}'").First();
        string status = row["Order Status"].ToString();
        dataGridView1[dataGridView1[dataGridView1.Columns["Status"].Index, e.RowIndex].Value = status;
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...