Необходимо работать с базой данных из разных потоков. База данных MySql, подключаюсь через Connector.NET.Для каждого потока хочу создать своё подключение к базе данных (пишет в базу данных только один поток, остальные только читают), т.е. создаю объекты MySqlConnection для каждого потока. Обращение к базе данных идёт из разных функций, разных классов. Для этого я создал ряд статических функций. Для работы этих функций необходимо передавать соответствующие ссылки на объекты MySqlConnection. Передавать эти ссылки в качестве параметра неудобно из-за вложенности функций. Хотелось бы в рамках каждого потока в любом месте кода иметь доступ к объекту MySqlConnection данного потока, т.е. иметь глобальную переменную в рамках потока.
Как это сделать.
Здравствуйте, cipher, Вы писали:
C>Необходимо работать с базой данных из разных потоков. База данных MySql, подключаюсь через Connector.NET.Для каждого потока хочу создать своё подключение к базе данных (пишет в базу данных только один поток, остальные только читают), т.е. создаю объекты MySqlConnection для каждого потока. Обращение к базе данных идёт из разных функций, разных классов. Для этого я создал ряд статических функций. Для работы этих функций необходимо передавать соответствующие ссылки на объекты MySqlConnection. Передавать эти ссылки в качестве параметра неудобно из-за вложенности функций. Хотелось бы в рамках каждого потока в любом месте кода иметь доступ к объекту MySqlConnection данного потока, т.е. иметь глобальную переменную в рамках потока. C>Как это сделать.
, но от себя добавлю, что для тех же целей ещё можно напрямую использовать методы GetData()/SetData() ( + AllocateDataSlot/AllocateNamedDataSlot/GetNamedDataSlot) у класса System.Threading.Thread. Прийдётся написать больше кода, но такое решение является более гибким.
Здравствуйте, Oyster, Вы писали:
C>>Как это сделать.
O>…для тех же целей ещё можно напрямую использовать методы GetData()/SetData() ( + AllocateDataSlot/AllocateNamedDataSlot/GetNamedDataSlot) у класса System.Threading.Thread. Прийдётся написать больше кода, но такое решение является более гибким.
А в чём гибкость? Минусы: отсутствие проверок со стороны компилятора на то, что данные в принципе есть и слабая типизация.
... << RSDN@Home 1.2.0 alpha rev. 670>>
Now playing: «Тихо в лесу…»
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, _FRED_, Вы писали:
_FR>А в чём гибкость? Минусы: отсутствие проверок со стороны компилятора на то, что данные в принципе есть и слабая типизация.
Плюсы — можно сделать сколько угодно слотов, т.е. полезно, если количество данных уровня потока, которые тебе надо будет хранить, известно только на этапе выполнения. Конечно, можно сделать List<object> или Dictionary<string, object> и пометить его [ThreadStatic], так что этот плюс сомнителен, пожалуй.
Второй плюс — если тебе вдруг захочется перейти с TLS на хранилище уровня Call Context-а, например. В случае с атрибутами прийдётся все их менять на [ContextStatic], в случае же с использованием GetData()/SetData() можно будет написать свою обёртку и абстрагироваться от собственно места хранилища (использовать CallContext, если понадобится). Мы как раз на такой ситуации обожглись, когда выяснили, что в ASP.NET 2.0 контекст одного реквеста может за время своей жизни сменить несколько потоков и пришлось избавляться от [ThreadStatic] (описано, например, тут: http://www.hanselman.com/blog/ATaleOfTwoTechniquesTheThreadStaticAttributeAndSystemWebHttpContextCurrentItems.aspx).
Здравствуйте, Oyster, Вы писали:
O>Второй плюс — если тебе вдруг захочется перейти с TLS на хранилище уровня Call Context-а, например. В случае с атрибутами прийдётся все их менять на [ContextStatic], в случае же с использованием GetData()/SetData() можно будет написать свою обёртку и абстрагироваться от собственно места хранилища (использовать CallContext, если понадобится). Мы как раз на такой ситуации обожглись, когда выяснили, что в ASP.NET 2.0 контекст одного реквеста может за время своей жизни сменить несколько потоков и пришлось избавляться от [ThreadStatic] (описано, например, тут: http://www.hanselman.com/blog/ATaleOfTwoTechniquesTheThreadStaticAttributeAndSystemWebHttpContextCurrentItems.aspx).
Да, гхм, интересно, но не будет ли это "преждевременной оптимизацией"
Help will always be given at Hogwarts to those who ask for it.
Здравствуйте, _FRED_, Вы писали:
_FR>Да, гхм, интересно, но не будет ли это "преждевременной оптимизацией"
А тут уж по ситуации надо смотреть. Конечно, в конкретной ситуации, описанной автором первого поста, [ThreadStatic] хватит. Я лишь описал, почему GetData()/SetData() может быть лучше.
Мы вот тоже думали, что [ThreadStatic] хватит навсегда... пока не столкнулись с этой проблемой в ASP.NET
Здравствуйте, Oyster, Вы писали:
O>Второй плюс — если тебе вдруг захочется перейти с TLS на хранилище уровня Call Context-а, например. В случае с атрибутами прийдётся все их менять на [ContextStatic], в случае же с использованием GetData()/SetData() можно будет написать свою обёртку и абстрагироваться от собственно места хранилища (использовать CallContext, если понадобится).
Так опять-таки проще будет использовать атрибуты ThreadStatic/ContextStatic, только внутри обертки — и переход сделать легко, и ручной работы не в пример меньше.
Здравствуйте, cipher, Вы писали:
C>Необходимо работать с базой данных из разных потоков. База данных MySql, подключаюсь через Connector.NET.Для каждого потока хочу создать своё подключение к базе данных (пишет в базу данных только один поток, остальные только читают), т.е. создаю объекты MySqlConnection для каждого потока. Обращение к базе данных идёт из разных функций, разных классов. Для этого я создал ряд статических функций. Для работы этих функций необходимо передавать соответствующие ссылки на объекты MySqlConnection. Передавать эти ссылки в качестве параметра неудобно из-за вложенности функций. Хотелось бы в рамках каждого потока в любом месте кода иметь доступ к объекту MySqlConnection данного потока, т.е. иметь глобальную переменную в рамках потока. C>Как это сделать.
Гм. Не знаю кто как, а вот лично я бы сделал проще — я бы избавился насколько это возможно от статических функций... Так ли нужны они ? Не проще ли сделать некий класс, экземпляр которого внутри себя будет содержать экземпляр подключения а также собственно сам рабочий поток с бизнес-логикой ?
Или, как вариант, сделать некий "пул соединений", глобальный для приложения и из рабочих потоков эти соединения дергать по необходимости ?
Или, (имхо лучший вариант) заюзать какую-нибудь ORM либу (да хотя бы тот же NHibernate) и наслаждаться (заодно и поддержка многих SQL серверов будет "почти автоматом", при правильном подходе конечно)
Здравствуйте, alexanderfedin, Вы писали:
A>Так опять-таки проще будет использовать атрибуты ThreadStatic/ContextStatic, только внутри обертки — и переход сделать легко, и ручной работы не в пример меньше.
Ну это пока тебе не захочется применить "внизу" то, для чего атрибута нет Например, Call Context-а на самом деле недостаточно для решения описанной проблемы с ASP.NET — нам в итоге пришлось в зависимости от приложения (не-ASP.NET или ASP.NET) использовать или Call Context, или HttpContext.Current.Items (для которого атрибутов уже нет и который хоть и использует CallContext, но как-то по особому поддерживается рантаймом ASP.NET, в результате чего при использовании его проблемы полностью уходят).
Здравствуйте, alexanderfedin, Вы писали:
A>Так опять-таки проще будет использовать атрибуты ThreadStatic/ContextStatic, только внутри обертки — и переход сделать легко, и ручной работы не в пример меньше.
O>добавлю, что для тех же целей ещё можно напрямую использовать методы GetData()/SetData() ( + AllocateDataSlot/AllocateNamedDataSlot/GetNamedDataSlot) у класса System.Threading.Thread. Прийдётся написать больше кода, но такое решение является более гибким.