EF вставка значений в таблицу не удалась через некоторое время

Я работаю над EF. Я пытаюсь вставить в таблицу, функция вставки находится в потоке.

private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
    int bytes = port.BytesToRead;
    //string indata = sp.ReadExisting();

    Thread.Sleep(50);

    try
    {
        receivedBytes = port.BaseStream.Read(buffer, 0, (int)buffer.Length);
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.Message.ToString());
    }

    var receiveData = BitConverter.ToString(buffer, 0, receivedBytes);
    var finalData = receiveData.Replace("-", "");
    //Thread.Sleep(100);

    Console.WriteLine("Thread Going to Start");

    new Thread(() => {
            SaveData(finalData);
        }).Start(); // starting the thread

    port.DiscardOutBuffer(); 
    port.DiscardInBuffer();
}

И это моя функция сохранения данных

public void SaveData(string finalData)
{
    Console.WriteLine(LineNumber() + "Data Transmiting...");
    thread = Thread.CurrentThread;         


mdc_dbEntities e = new mdc_dbEntities();

            var msn = e.mdc_meter_config.Where(m => m.m_hex == sr).Select(s => new { s.msn, s.p_id, s.meter_id }).ToList();

    var H = finalData.Substring(0, 2);

    using (mdc_dbEntities u = new mdc_dbEntities())
    {
        foreach (var res in msn)
        {
            var cust_id = e.mdc_meter_cust_rel.Where(m => m.msn == res.msn)
                                              .Select(s => s.cust_id)
                                              .FirstOrDefault();

            mdc_meters_data data = new mdc_meters_data()
                    {
                        msn = res.msn,
                        cust_id = cust_id,
                        device_id = res.meter_id.ToString(),
                        kwh = e_val.ToString(),
                        voltage_p1 = a_vol_val.ToString(),
                        voltage_p2 = b_vol_val.ToString(),
                        voltage_p3 = c_vol_val.ToString(),
                        current_p1 = a_curr_val.ToString(),
                        current_p2 = b_curr_val.ToString(),
                        current_p3 = c_curr_val.ToString(),
                        data_date_time = Convert.ToDateTime(theDate.ToString(format)),
                        d_type = d_type.ToString(),
                        pf1 = a_pf_val.ToString(),
                        pf2 = b_pf_val.ToString(),
                        pf3 = c_pf_val.ToString(),
                        p_id = res.p_id,
                    };
            u.mdc_meters_data.Add(data);
        }

        u.SaveChanges();
    }

    Console.WriteLine(LineNumber() + "Data Saved");
    Thread.Sleep(50);
}

try
{
    thread.Abort(); // aborting it after insertion
    //Thread.Sleep(50);
}
catch (Exception ex)
{
    Console.WriteLine(ex.Message.ToString());
}
}

Приведенный выше код работает некоторое время, но после этого я обнаружил ошибку на u.SaveChanges();

System.Data.Entity.Core.EntityException: «Произошла ошибка при закрытии соединения с поставщиком. См. Подробности во внутреннем исключении. '

MySqlException: во время выполнения команды произошла фатальная ошибка.
MySqlException: произошла фатальная ошибка при попытке чтения набора результатов.
MySqlException: чтение из потока завершилось неудачно.

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

SocketException: попытка подключения не удалась, потому что подключенная сторона не ответила должным образом по прошествии определенного периода времени, или установленное соединение не удалось, потому что подключенный хост не ответил

Я изучил каждое решение и попробовал их, но все еще не могу решить эту проблему. Должно быть, мне не хватает чего-то, чего я не знаю.

Обновить 1 весь мой код

Вызов конструктора

  public CommunicationEngine()
    {
        port.ReadTimeout = 500;
        port.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
        port.Open();

        Console.WriteLine("Port opened successfully");

        Console.WriteLine("I am Recieving");
    }

Обработчик вызовов

 private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
    {

        int bytes = port.BytesToRead;


        Thread.Sleep(50);
        Console.WriteLine("Bytes are ok..." + port.BytesToRead + " Recieved ");
        try
        {
            receivedBytes = port.BaseStream.Read(buffer, 0, (int)buffer.Length);

        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message.ToString());
        }


        var receiveData = BitConverter.ToString(buffer, 0, receivedBytes);
        var finalData = receiveData.Replace("-", "");
        //Thread.Sleep(100);

        Console.WriteLine("Thread Going to Start");

        try
        {
            new Thread(() => {
                SaveData(finalData);
            }).Start();
        }
        catch(Exception ex)
        {
            Console.WriteLine(ex.Message.ToString());
        }          


        port.DiscardOutBuffer(); port.DiscardInBuffer();



    }

Сохранение данных в БД

public void SaveData(string finalData)
    {

        Console.WriteLine(LineNumber() + "Data Transmiting...");
        thread = Thread.CurrentThread;

        if (finalData.Length == 138)
        {
            comm = true;

            var H = finalData.Substring(0, 2);

            var FC = finalData.Substring(2, 9);

            var len = finalData.Substring(10, 2);

            var sr = finalData.Substring(12, 12);

            var energy_tag = finalData.Substring(24, 4);

            var e_val = hexToDec(finalData.Substring(28, 8)) / 10;

            var a_curr_tag = finalData.Substring(36, 4);

            var a_curr_val = hexToDec(finalData.Substring(40, 8)) / 1000;

            var b_curr_tag = finalData.Substring(48, 4);

            var b_curr_val = hexToDec(finalData.Substring(52, 8)) / 1000;

            var c_curr_tag = finalData.Substring(60, 4);

            var c_curr_val = hexToDec(finalData.Substring(64, 8)) / 1000;

            var a_vol_tag = finalData.Substring(72, 4);

            var a_vol_val = hexToDec(finalData.Substring(76, 8)) / 10;

            var b_vol_tag = finalData.Substring(84, 4);

            var b_vol_val = hexToDec(finalData.Substring(88, 8)) / 10;

            var c_vol_tag = finalData.Substring(96, 4);

            var c_vol_val = hexToDec(finalData.Substring(100, 8)) / 10;

            var a_pf_tag = finalData.Substring(108, 4);

            var a_pf_val = hexToDec(finalData.Substring(112, 4)) / 1000;

            var b_pf_tag = finalData.Substring(116, 4);

            var b_pf_val = hexToDec(finalData.Substring(120, 4)) / 1000;

            var c_pf_tag = finalData.Substring(124, 4);

            var c_pf_val = hexToDec(finalData.Substring(128, 4)) / 1000;

            var crc = finalData.Substring(132, 4);

            var ftr = finalData.Substring(136, 2);


            var d_type = "600";

            DateTime theDate = DateTime.Now;

            string format = "yyyy-MM-dd HH:mm:ss";
            Console.WriteLine(LineNumber() + "Data Ready to be inserted in DB");
            using (mdc_dbEntities u = new mdc_dbEntities())
            {
                var msnList = u.mdc_meter_config.Where(m => m.m_hex == sr)
                .Select(s => new { s.msn, s.p_id, s.meter_id })
                .ToList();

                foreach (var res in msnList)
                {
                    var cust_id = u.mdc_meter_cust_rel.Where(m => m.msn == res.msn)
                        .Select(s => s.cust_id)
                        .FirstOrDefault();

                    mdc_meters_data data = new mdc_meters_data()
                    {
                        msn = res.msn,
                        cust_id = cust_id,
                        device_id = res.meter_id.ToString(),
                        kwh = e_val.ToString(),
                        voltage_p1 = a_vol_val.ToString(),
                        voltage_p2 = b_vol_val.ToString(),
                        voltage_p3 = c_vol_val.ToString(),
                        current_p1 = a_curr_val.ToString(),
                        current_p2 = b_curr_val.ToString(),
                        current_p3 = c_curr_val.ToString(),
                        data_date_time = Convert.ToDateTime(theDate.ToString(format)),
                        d_type = d_type.ToString(),
                        pf1 = a_pf_val.ToString(),
                        pf2 = b_pf_val.ToString(),
                        pf3 = c_pf_val.ToString(),
                        p_id = res.p_id,
                    };
                    u.mdc_meters_data.Add(data);

                }
                try
                {
                    u.SaveChanges();
                }
                catch(Exception ex)
                {
                    Console.WriteLine(ex.Message.ToString());
                }

            }                

            Console.WriteLine(LineNumber() + "Data Saved");
            Thread.Sleep(50);

        }
        else if(finalData.Length == 30)
        {
            var msn_no = finalData.Substring(12, 12);

            mdc_dbEntities p = new mdc_dbEntities();

            var update = p.meter_control.Where(c => (c.comm_executed == 0))
                          .Where(o => (o.m_hex == msn_no))
                          .SingleOrDefault();

            if(update.comm_sent == "Disconnect")
            {
                update.comm_executed = 1;
                update.comm = 0;
                p.SaveChanges();
                Console.WriteLine("Meter Disconnected....");
            }
            else if(update.comm_sent == "Connect")
            {

                update.comm_executed = 1;
                update.comm = 1;
                p.SaveChanges();
                Console.WriteLine("Meter Connected....");
            }             

            comm = true;
        }
        else
        {
            comm = true;
        }

        try
        {
            thread.Abort();

        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message.ToString());
        }

    }

Любая помощь будет высоко ценится.


person Moeez    schedule 08.06.2020    source источник
comment
var cust_id = e.mdc_meter_cust_rel.Where(m => m.msn == res.msn) .Select(s => s.cust_id).FirstOrDefault(); что такое е   -  person Seabizkit    schedule 10.06.2020
comment
что такое msn и каково его количество обычно   -  person Seabizkit    schedule 10.06.2020
comment
@Seabizkit msn - серийный номер. e - объект моего dbcontext. mdc_dbEntities e = new mdc_dbEntities(); var msn = e.mdc_meter_config.Where(m => m.m_hex == sr).Select(s => new { s.msn, s.p_id, s.meter_id }).ToList();   -  person Moeez    schedule 10.06.2020
comment
В отличие от u, который создается с помощью блока using, я не вижу кода, чтобы избавиться от mdc_dbEntities e = new mdc_dbEntities();. Поэтому я подозреваю, что вы накапливаете больше открытых соединений, пока сервер или клиент не перестанут их принимать. Но я бы также рекомендовал переосмыслить подход, основанный на потоках. Возможно, вам лучше было бы работать с Task.   -  person grek40    schedule 10.06.2020
comment
Контекст e должен закрыть свое соединение после прочтения. Все-таки лучше завернуть в using. Но почему вы создаете два однотипных контекста? В этом нет необходимости. Тем не менее, внешние переменные port и receivedBytes указывают, что этот код не может быть потокобезопасным, если эти объекты не являются потокобезопасными. Скорее всего, нет. Я бы начал делать ваш код потокобезопасным, что будет проще при его рефакторинге до синтаксиса async-await. Тогда это тоже проще отладить.   -  person Gert Arnold    schedule 10.06.2020
comment
присмотритесь, вы используете e, где вы должны использовать 'u' e.mdc_meter_cust_rel.Where(m => m.msn == res.msn)   -  person Seabizkit    schedule 10.06.2020
comment
Не прерывайте цепочки.   -  person satnhak    schedule 10.06.2020
comment
Я предполагаю, что соединение с вашим хостом БД внезапно закрывается, EF пытается повторно использовать его, потому что он не был проинформирован о закрытии соединения, отправляет запрос и время ожидания истекает. Обычно это происходит, если между вами и вашим провайдером БД неправильно настроен прокси / брандмауэр. В этом случае лучшее, что вы можете сделать, - это защитить свою функцию с помощью try / catch, принудительно закрыть соединение с помощью dbContext.Connection.Close(); и повторить операцию с новым контекстом, чтобы убедиться, что оно создает новое соединение.   -  person Gusman    schedule 13.06.2020


Ответы (2)


Выполнение связанных с EF изменений в потоке, инициированном вручную, не является хорошей идеей. Попробуйте запустить изменения EF в том же потоке. Если вас беспокоит обработка входящих запросов, используйте функции Async и Await. Я изменил ваш код, чтобы учесть эту функцию. Пожалуйста, попробуйте это.

private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
    int bytes = port.BytesToRead;
    //string indata = sp.ReadExisting();

    try
    {
        receivedBytes = port.BaseStream.Read(buffer, 0, (int)buffer.Length);
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.Message.ToString());
    }

    var receiveData = BitConverter.ToString(buffer, 0, receivedBytes);
    var finalData = receiveData.Replace("-", "");

    Console.WriteLine("Thread Going to Start");

    SaveDataAsync(finalData).Wait(); // this call will become sync and runs under main thread.

    port.DiscardOutBuffer(); 
    port.DiscardInBuffer();
}

public async Task<bool> SaveDataAsync(string finalData)
{
mdc_dbEntities e = new mdc_dbEntities();

            var msn = e.mdc_meter_config.Where(m => m.m_hex == sr).Select(s => new { s.msn, s.p_id, s.meter_id }).ToList();

    var H = finalData.Substring(0, 2);
var isSaveSuccess = false;
    using (mdc_dbEntities u = new mdc_dbEntities())
    {
        foreach (var res in msn)
        {
            var cust_id = e.mdc_meter_cust_rel.Where(m => m.msn == res.msn)
                                              .Select(s => s.cust_id)
                                              .FirstOrDefault();

            mdc_meters_data data = new mdc_meters_data()
                    {
                        msn = res.msn,
                        cust_id = cust_id,
                        device_id = res.meter_id.ToString(),
                        kwh = e_val.ToString(),
                        voltage_p1 = a_vol_val.ToString(),
                        voltage_p2 = b_vol_val.ToString(),
                        voltage_p3 = c_vol_val.ToString(),
                        current_p1 = a_curr_val.ToString(),
                        current_p2 = b_curr_val.ToString(),
                        current_p3 = c_curr_val.ToString(),
                        data_date_time = Convert.ToDateTime(theDate.ToString(format)),
                        d_type = d_type.ToString(),
                        pf1 = a_pf_val.ToString(),
                        pf2 = b_pf_val.ToString(),
                        pf3 = c_pf_val.ToString(),
                        p_id = res.p_id,
                    };
            u.mdc_meters_data.Add(data);
        }

       isSaveSuccess = (await u.SaveChangesAsync())>0; // if records inserted, the count will be more than 0
    }

   return isSaveSuccess;
}

}
person Karthik    schedule 16.06.2020
comment
@Faisal - Вы пробовали это? удалось ли вам добиться успеха? - person Karthik; 16.06.2020
comment
Я звоню DataReceivedHandler вот так port.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);, и это вызывает ошибку 'Task CommunicationEngine.DataReceivedHandler(object, SerialDataReceivedEventArgs)' has the wrong return - person Moeez; 17.06.2020
comment
@Faisal - обновил ответ. сделал вызов SaveDataAsync (finalData) .Wait () для синхронизации, чтобы подпись SerialDataReceivedEventHandler не изменилась. Пожалуйста, попробуйте сейчас - person Karthik; 17.06.2020
comment
Я также пробовал ваш обновленный код. Теперь мне не возвращаются полные байты. В этом случае данные не сохраняются в базе данных - person Moeez; 19.06.2020
comment
Я добавил весь свой код (исходный). Пожалуйста, посмотрите. - person Moeez; 19.06.2020
comment
@Faisal - какое условие IF выполняется при отладке кода? Кроме того, если у вас есть SaveChanges (), назначьте его переменной, например var saveCount = SaveChanges (); и отлаживаем код. если переменная имеет счетчик как 0, то, скорее всего, отслеживание сущностей не происходит. Я упрощу ваш код и дам вам знать. А пока попробуйте это и поделитесь своим обновлением - person Karthik; 19.06.2020
comment
В последней части этого не будет :( - person Moeez; 19.06.2020
comment
@Faisal - что такое finalData.length? на основе этого значения он переходит в часть IF, ELSEIF или ELSE. каково значение update.comm_sent? если вы говорите о последней части else, это означает, что finalData.Length не 138 и 30. Так что нечего будет добавлять и сохранять в БД. Если мое понимание неверно, вам нужно четко объяснить, какая строка вашего кода выполняется и что ожидается? - person Karthik; 19.06.2020
comment
Да Это ни 138, ни 30. Ошибка, о которой я говорю, относится к 1-й, если условие if(finalData.length == 138) - person Moeez; 19.06.2020

это легче читать и может помочь

говоря все это, убедитесь, что вы действительно можете установить соединение с db double check connectionString

public void SaveData(string finalData)
{
    Console.WriteLine(LineNumber() + "Data Transmiting...");

    using (mdc_dbEntities dbContext = new mdc_dbEntities())
    {
        var msnList = dbContext.mdc_meter_config.Where(m => m.m_hex == sr)
                    .Select(s => new { s.msn, s.p_id, s.meter_id })
                    .ToList();

        //put debug point here and check that msnList is populated
        foreach (var item in msnList)
        {
            //this is slow as it will be a db query for each loop
            var cust_id = dbContext.mdc_meter_cust_rel.Where(m => m.msn == item.msn)
                                   .Select(s => s.cust_id)
                                   .FirstOrDefault();

            var data = new mdc_meters_data()
            {
                msn = item.msn,
                cust_id = cust_id,
                device_id = item.meter_id.ToString(),
                kwh = e_val.ToString(),
                voltage_p1 = a_vol_val.ToString(),
                voltage_p2 = b_vol_val.ToString(),
                voltage_p3 = c_vol_val.ToString(),
                current_p1 = a_curr_val.ToString(),
                current_p2 = b_curr_val.ToString(),
                current_p3 = c_curr_val.ToString(),
                data_date_time = Convert.ToDateTime(theDate.ToString(format)),
                d_type = d_type.ToString(),
                pf1 = a_pf_val.ToString(),
                pf2 = b_pf_val.ToString(),
                pf3 = c_pf_val.ToString(),
                p_id = item.p_id,
            };
            dbContext.mdc_meters_data.Add(data);
        }

        //depending on how many you added this may take some time.
        dbContext.SaveChanges();
    }
}
person Seabizkit    schedule 10.06.2020
comment
Пробовал, но проблема не исчезла - person Moeez; 15.06.2020
comment
Итак, вы используете приведенный выше код и получаете эту ошибку? вы уверены!! пожалуйста, дважды проверьте @Faisal - person Seabizkit; 15.06.2020
comment
сделайте это в том же потоке и посмотрите, если возникнет проблема, удалите new Thread(() => { и `}). Start (); // запускаем поток` - person Seabizkit; 15.06.2020
comment
Что еще интереснее, вы передаете string finalData) в метод, а затем даже не используете его - person Seabizkit; 15.06.2020