Не работает сохранение изменений данных для одной из таблиц в .Net C#

Я сохраняю изменения в таблице базы по нажатию на кнопку, вот сам код:

else if (comboBox1.SelectedItem == "Элек")
{
label3.Text = "Электричество";
string script = "SELECT id, name, Mx_pw_VT, Pr_pw_VT, elec_kVT_hr, Print_time_fact, YZV_power_VT FROM elec;";
mycon = new MySqlConnection(connect);
mycon.Open();
MySqlDataAdapter ms_data = new MySqlDataAdapter(script, connect);
var cb = new MySqlCommandBuilder(ms_data);
cb.GetInsertCommand();
ms_data.Update(dataGridView1.DataSource as DataTable);
ms_data.InsertCommand = cb.GetInsertCommand();
ms_data.InsertCommand.CommandText += "; select * from elec where id = last_insert_id();";
ms_data.InsertCommand.UpdatedRowSource = UpdateRowSource.FirstReturnedRecord;
}

Но мне почему то выдает ошибку «Нарушение параллелизма: UpdateCommand затронула 0 из ожидаемых 1 записей.» Причем у меня есть такой же блок кода для другой таблицы и он работает, в этой таблице изменения происходят, сам блок:

else if (comboBox1.SelectedItem == "Рбт")
{
label3.Text = "Рбт";
string script = "SELECT id, name, Model_preparation_R_Hr, Time_for_preparation_hr, Time_for_post_processing_hr, YZV_work FROM rbt;";
mycon = new MySqlConnection(connect);
mycon.Open();
MySqlDataAdapter ms_data = new MySqlDataAdapter(script, connect);
var cb = new MySqlCommandBuilder(ms_data);
cb.GetInsertCommand();
ms_data.Update(dataGridView1.DataSource as DataTable);
ms_data.InsertCommand = cb.GetInsertCommand();
ms_data.InsertCommand.CommandText += "; select * from rbt where id = last_insert_id();";
ms_data.InsertCommand.UpdatedRowSource = UpdateRowSource.FirstReturnedRecord;
}

Что не так? Подскажите пожалуйста


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

Автор решения: Frehzy

Метод для получения и конвертации ответа от бд (использовать только с SELECT):

public List<T> SqlQuery<T>(string query)
    {
        var result = new List<T>();

        using (MySqlConnection connection = GetDBConnection(1))
        {
            connection.Open();
            using var command = connection.CreateCommand();
            command.CommandText = query;
            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;
    }

Метод для получения строки sql-запроса на вставку. Гораздо удобнее. Не нужно писать 1000 и 1 Insert строку для таблиц. Нужно лишь создать класс:

    public static string GetInsertSqlString<TValue>(TValue value, string tableName)
    {
        var columnsName = value.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance).Select(x => x.Name).ToArray();
        var values = value.GetType()
            .GetProperties(BindingFlags.Public | BindingFlags.Instance)
            .Select(x => x.GetValue(value, null));
        var hasBool = values.FirstOrDefault(x => x.GetType() == typeof(bool)) is not null;
        if (hasBool is false)
            return $"INSERT INTO {tableName}({string.Join(",", columnsName)}) VALUES ('{string.Join("','", values)}')";
        else
        {
            List<string> valuesWithBool = new();
            foreach (var val in values)
                if (val.GetType().Equals(typeof(bool)))
                    valuesWithBool.Add(val.ToString());
                else
                    valuesWithBool.Add($"'{val}'");

            return $"INSERT INTO {tableName}({string.Join(",", columnsName)}) VALUES ({string.Join(",", valuesWithBool)})";
        }
    }

Метод для Insert:

public DBResponseStatus ExecuteNonQuery(string query)
    {
        using MySqlConnection myConnection = GetDBConnection();
        try
        {
            if (myConnection.State == ConnectionState.Closed)
                myConnection.Open();

            MySqlCommand command = new(query, myConnection);
            command.ExecuteNonQuery();
            return DBResponseStatus.OK;
        }
        catch (Exception ex)
        {
            Log.Error(ex.ToString());
            return DBResponseStatus.Error;
        }
    }

Перечисление, которое возвращается из метода ExecuteNonQuery:

public enum DBResponseStatus
{
    OK = 0,
    Error = 1
}

Метод GetDBConnection для получения строки для БД:

public MySqlConnection GetDBConnection(int timeOut = 30)
    {
        string connString = "Server=" + Host
            + ";Database=" + DataBaseName
            + ";port=" + Port
            + ";User Id=" + Username
            + ";password=" + Password
            + ";Connection Timeout=" + timeOut;

        MySqlConnection conn = new(connString);

        return conn;
    }

Пример класса для нормальной работы методов:

internal class ProductDB
{
    public Guid OrderId { get; set; }

    public Guid ProductId { get; set; }

    public ProductDB() { }

    public ProductDB(Guid orderId, Guid productID)
    {
        OrderId = orderId;
        ProductId = productID;
    }
}

Пример вызова метода SqlQuery для Select:

List<Product> GetProducts() =>
            DB.SqlQuery<Product>("SELECT * FROM products");

Пример вызова метода ExecuteNonQuery для Insert:

db.ExecuteNonQuery(SQLString.GetInsertSqlString(*экземпляр класса*, "ordersproducts"));
→ Ссылка