System.Data.OleDb.OleDbException: "Отсутствует значение для одного или нескольких требуемых параметров. C# Windows Forms + Microsoft Access

Выдает ошибку в следующей функции:

public void Tipmat(string tipmat)
{
    connection.Open();
    command = new OleDbCommand($"SELECT * FROM Материал WHERE Тип_мат = [{tipmat}]", connection);
    command.ExecuteNonQuery();
    connection.Close();
}

При вызове функции, tipmat принимает одно из четырех значений (Детали, Раст_жив_сырье, Горючее_сырье, Инструменты) в зависимости от того, что выбрал пользователь в комбо боксе. Функция вызывается когда пользователь меняет значение в комбо боксе.

Комбо

введите сюда описание изображения

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

Таблица


Ответы (2 шт):

Автор решения: Антон К.

Вероятно, у вас ошибка в строке запроса. Попробуйте изменить свой код так:

    command = new OleDbCommand($"SELECT * FROM Материал WHERE Тип_мат = '{tipmat}'", connection);

Здесь мы просто берем в кавычки значение, передаваемое в запрос.

→ Ссылка
Автор решения: Frehzy

Используйте параметризированные запросы - https://metanit.com/sharp/adonet/2.9.php

После создания такого запроса (с нужными параметрами и тд), открывайте соединение, передавайте command в метод и закрывайте его.

Для конвертации полученных данных в List используйте следующий код:

public List<T> SqlQuery<T>(MySqlCommand command)
{
    var result = new List<T>();
    using var reader = command.ExecuteReader();
    var columns = Enumerable.Range(0, reader.FieldCount).Select(reader.GetName).ToArray();
    var properties = typeof(T).GetProperties();

    while (reader.Read())
    {
        var data = new object[reader.FieldCount];
        reader.GetValues(data);

        var instance = (T)Activator.CreateInstance(typeof(T));

        for (var i = 0; i < data.Length; ++i)
        {
            if (data[i] == DBNull.Value)
                data[i] = null;

            var property = properties.SingleOrDefault(x => x.Name.Equals(columns[i], StringComparison.InvariantCultureIgnoreCase));

            if (property is not null)
            {
                var dataValue = Guid.TryParse(data[i].ToString(), out Guid res) is true ? res : data[i];
                property.SetValue(instance, Convert.ChangeType(dataValue, property.PropertyType));
            }
        }
        result.Add(instance);
    }
    return result;
}

Не забывайте открывать и закрывать соединение. Проще всего это делать, заворачивая connection в using.

Пример использования:

List<T> GetMaterialsByType(MySqlConnection connection, MaterialTypeEnum materialTypeEnum)
{
    using (connection)
    {
        connection.Open();

        using var command = connection.CreateCommand();
        command.CommandText = "SELECT * FROM Материал WHERE Тип_мат = @MaterType";
        command.Parameters.AddWithValue("@MaterType", materialTypeEnum);
        return SqlQuery(command);
    }
}

enum MaterialTypeEnum //Лучше храните одинаковые типы в enum. Гораздо проще жизнь станет
{
    Iron = 0,
    Wood = 1
}

UPD:

Заметил, как вы именуете методы. Слов, кроме как, "Wtf?!" не могу подобрать. Неужто нельзя назвать метод по получению списка материалов как-нибудь типо GetMaterialsByType, как у меня выше в примере.

Прошу, прочтите данную статью для приведения вашего стиля написания кода в порядок https://docs.microsoft.com/en-us/dotnet/csharp/fundamentals/coding-style/coding-conventions

→ Ссылка