Куда поместить использование (SqlConnection)

Я создаю структуру для добавления плагинов в мое приложение. Каждый плагин должен реализовывать абстрактный класс. Затем каждый плагин компилируется как DLL, которую основное приложение может найти с помощью Directory.GetFiles(myPath, "*.dll")

Все это работает плавно, и я могу создавать свои плагины в основном приложении и использовать их. Каждый плагин в основном представляет собой виджет панели инструментов, который пользователь может добавить на свою панель инструментов, чтобы показать ему некоторые графики или диаграммы. Это означает, что у каждого плагина есть таймер, и при каждом событии таймера он обновляет график данными из базы данных SQL приложения.

Итак, мой вопрос: куда мне поставить SqlConnection? Создать один SqlConnection и передать его в качестве параметра каждому плагину или передать строку подключения, и каждый плагин создаст свой собственный SqlConnection?

Если я передам SqlConnection приложения плагину, то я полагаю, что это потребует некоторого управления соединением внутри плагина. Я, очевидно, должен проверить, что он открыт, и что мне делать, если его состояние ConnectionState.Fetching или ConnectionState.Executing? Это только кажется громоздким.

Но, с другой стороны, учитывая, что приложение будет запущено несколькими пользователями, и у каждого пользователя может быть несколько плагинов, выбранных на его панели инструментов, в сумме это может составить SqlConnections. Это желательно? Должен ли я рассмотреть третий вариант, когда плагин отправляет свой запрос хосту, который ставит его в очередь с другими запросами от других плагинов и возвращает набор результатов плагину после выполнения запроса? Таким образом, по крайней мере, у каждого пользователя будет только один SqlConnection, независимо от того, сколько плагинов он выбрал.

Честно говоря, этот последний вариант кажется мне довольно сложным, и я пока не совсем уверен, как бы я его реализовал. Если бы кто-нибудь мог указать мне на статью, которая объясняет что-то подобное, я был бы очень признателен.


person Dewald Swanepoel    schedule 25.04.2015    source источник


Ответы (2)


Лично я бы порекомендовал передать фабрику соединений вашим плагинам и позволить им создавать и использовать соединения по своему усмотрению. Это означает, что ваше приложение контролирует строку подключения (хотя потенциально они все еще могут читать ее из подключения, если вы также не абстрагируете это), но они могут свободно создавать и использовать подключения по мере необходимости. Как указывалось в предыдущем ответе, если вы просто предоставите им одно соединение, потребуется много работы для решения проблем с многопоточностью и проблемами совместного использования, о которых вы сами упомянули.

Вы можете сделать что-то простое, например:

public interface ISqlConnectionFactory
{
   SqlConnection GenerateConnection();
}

public class SqlConnectionFactory : ISqlConnectionFactory
{
   private readonly string _connectionString;

   public SqlConnectionFactory()
   {
      _connectionString = "your connection string here";
   }

   public SqlConnection GenerateConnection()
   {
       return new SqlConnection(_connectionString);
   }
}

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

ИЗМЕНИТЬ

Безусловно, ваши плагины должны использовать оператор using():

public void MyPluginMain(ISqlConnectionFactory factory)
{
   using(var connection = factory.GenerateConnection())
   {
      // Do the work
   }
}

Принимая во внимание, что ваше приложение перекладывает ответственность за поддержание этих подключений на подключаемые модули, подключаемый модуль должен очищать соединение после завершения работы с ним, будь то оператором using() или фактическим вызовом Dispose() после он сделал то, что сделал. Если это какой-либо «общедоступный» API, он должен быть частью вашей документации.

person CodingGorilla    schedule 25.04.2015
comment
Спасибо, это звучит как более простой подход. Я не знаком с фабрикой соединений. Я сейчас гуглю, но если у вас есть статья или что-то подходящее, на что вы можете мне указать, это было бы здорово. - person Dewald Swanepoel; 25.04.2015
comment
Классные бананы. Я только что увидел обновление. Выглядит очень элегантно. Я думаю, что это путь, которым я буду следовать. Я не думаю, что в этом случае плагин сможет использовать использование (SqlConnection)? - person Dewald Swanepoel; 25.04.2015
comment
Фабрика соединений также может иметь метод GenerateConnection(), помещающий каждое соединение в список, а при удалении плагина проверяйте, что каждое соединение в списке также удаляется. - person Joel Coehoorn; 26.04.2015

Вы не должны совместно использовать соединение между различными плагинами, вместо этого создайте его внутри плагина или даже для каждого запроса. Это не повредит производительности, они предназначены для такого использования.

См. раздел SqlConnection и многопоточность.

person Michael Sander    schedule 25.04.2015