C# Ошибка в SingleTon?

202
24 января 2019, 12:40

Есть файл кастомных конфигураций для нескольких клиентов, которые я держу в памяти через Single Ton. Долго все работало без проблем но тут внезапно прилетела заявка от клиента, что одна из транзакций совершалась по одному клиенту, а прилитела на счет другого. Мне кажется я догадываюсь в чем дело, но очень нужен взгляд со стороны (подозреваю, что это и вовсе может быть вредительство определенных лиц имеющих доступ к конфигу, но это не точно). Код старался максимально обезличить, но по запросу предоставлю всю необходимую дополнительную информацию. Может ли сатический метод Веб-приложения вернуть данные одного клиента другому?

Заранее спасибо за помощь.

using System;
using System.IO;
using System.Linq;
using System.Threading;
using System.Web.Configuration;
namespace App
{
    public class Settings
    {
        private static GetSettings _items = null;
        private static string path = "";
        static Settings()
        {
            //подписываемся на изменение файла
            FileSystemWatcher watcher = new FileSystemWatcher();
            watcher.Path = AppDomain.CurrentDomain.BaseDirectory;
            watcher.NotifyFilter = NotifyFilters.LastWrite;
            watcher.Filter = "Имя файла настроек";
            watcher.Changed += new FileSystemEventHandler(OnChanged);
            watcher.EnableRaisingEvents = true;
        }
        protected Settings()
        {
            ReadSettings("Конструктор");
        }
        private static GetSettings.Client GetSettingsForClient(string clientId)
        {
            try
            {
                if (_items != null && _items.Clients.Any())
                {
                    clientId = clientId.Trim();
                    return _items.Clients.First(x => x.ClientId.Equals(clientId));
                }
                else
                {
                    //logger
                    return null;
                }
            }
            catch (Exception e)
            {
                //logger
                return null;    
            }    
        }
        //метод, доступный из вне, который возвращает настройки клиента:
        public static GetSettings.Client GetSettings(string clientId)
        {
            GetSettings.Client clientInfo = null;
            try
            {
                for (int i = 0; i < 3; i++)
                    {
                        //SingleTon
                        if (_items == null || !_items.Clients.Any())
                        {
                            new Settings();
                        }
                        //думаю, что проблема вот здесь, но это не точно:
                        //метод статический и мы получилинастройки для одного клиента, а вернули эти настройки другому. 
                        //Но с другой тороны - если бы это было так - то транзакции были бы перепутаны местами, а у нас ситуация когда одна транзакция просто не по тому мерчанту прошла
                        clientInfo = GetSettingsForClient(clientId);
                        if (clientInfo != null) break;
                        Thread.Sleep(50);
                    }
                    return clientInfo;
                }
            catch (Exception e)
            {
                //logger
                return null;
            }
        }
        private static void OnChanged(object source, FileSystemEventArgs e)
        {
            ReadSettings("Событие OnChanged", e);
        }
        private static void ReadSettings(string method, FileSystemEventArgs e = null)
        {
            try
            {
                if (method == "Событие OnChanged")
                {//логеры старых и новых настроек добавлены после инцидента, так что я не знаю менялся ли файл
                    string oldSettings = _items != null ? Newtonsoft.Json.JsonConvert.SerializeObject(_items) : "На момент обновления файлоа конфигурации настройки не были загружены в память";
                    logger.SettingsLog("Выполнено изменение файла настроек. Старые настройки: \n\r" + oldSettings);
                }
                path = "путь к файлу";
                if (File.Exists("путь к файлу"))
                {
                    _items = ServicesMethod.DesserializeJsonFromFile(path, new GetSettings());
                    if (_items != null && method == "Событие OnChanged")
                    {
                        logger.SettingsLog("Новые настройки: " + Newtonsoft.Json.JsonConvert.SerializeObject(_items));
                    }
                }
                else
                {
                    //logger
                }
            }
            catch (ArgumentNullException ex)
            {
                //logger
            }
            catch (Exception ex)
            {
                //logger
            }
        }
    }
}
Answer 1

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

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

Вы в многопоточном окружении используете статическое поле, что очень плохо

    private static string path = "";

Это поле у вас используется при чтении файлов

            path = "путь к файлу";
            if (File.Exists("путь к файлу"))
            {
                _items = ServicesMethod.DesserializeJsonFromFile(path, new GetSettings());
                if (_items != null && method == "Событие OnChanged")
                {
                    .......
                }
            }

А теперь представьте 2 параллельных вызова к вашему методу, и в момент, когда первый вызов ещё не закончил свое выполнение, второй вызов изменил значение статического поля, которое всё ещё используется в первом вызове. То есть, по идее, после этого, оба вызова будут работать с одинаковым именем файла, не зависимо от того, с какими параметрами был сделан первый вызов.

READ ALSO
C#, Xamarin ошибка System.IO.FileNotFoundException при XmlDocument.LoadXml(string)

C#, Xamarin ошибка System.IO.FileNotFoundException при XmlDocument.LoadXml(string)

Код который у меня, ошибка на последней строчке

193
C# объединение и сумма одинаковых элементов в List

C# объединение и сумма одинаковых элементов в List

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

336
Entity Framework 5. Illegal mix of collations for operation &#39;UNION&#39;

Entity Framework 5. Illegal mix of collations for operation 'UNION'

Создал в MySQL тестовую базуОдна таблица:

177