В целом согласны с ответом Марка, но у меня есть другие комментарии и другой угол. Надеюсь, мой ответ будет вам полезен.
Во-первых, есть ничего плохого в использовании статических классов и методов в параллельной среде, если нет никакой необходимости в какой-либо информации о состоянии, и данные не распространяются. В вашем случае, заполняя DropDownList, это прекрасно, потому что вам нужен только список строк, и как только вы это сделаете, вы можете забыть все о том, как вы его получили. Также нет помех между параллельными вызовами статического метода, если они не имеют доступа к каким-либо статическим полям. Статические методы распространены в платформе .NET, и они являются потокобезопасными.
В моем примере ниже я использую одно статическое поле - log4net logger. Он по-прежнему является потокобезопасным, поскольку он не несет никакого состояния и является просто точкой перехода к библиотеке log4net, которая сама по себе является потокобезопасной. Порекомендуйте хотя бы взглянуть на log4net - отличную регистрацию lib.
Это может быть небезопасно, если вы попытались заполнить тот же раскрывающийся список из двух потоков, но тогда было бы также небезопасно, если бы этот класс не был статичным. Убедитесь, что выпадающие списки заполнены из одной (основной) нити.
Обратно к вашему коду.Смешивание пользовательского интерфейса и извлечение данных не является хорошей практикой, так как он делает код намного менее удобным и менее стабильным. Отделите эти два. Библиотека Dapper может быть хорошим способом упростить ситуацию. Я не использовал его сам, поэтому могу сказать, что он выглядит очень удобно и эффективно. Если вы хотите/должны узнать, как работает материал, не используйте его. По крайней мере, не поначалу.
Наличие непараметризированного запроса в одной строке потенциально подвержено атакам SQL-инъекций, но если этот запрос не сконструирован на основе любого прямого ввода пользователем, он должен быть безопасным. Конечно, вы всегда можете принять параметризацию, чтобы быть уверенным.
Обработка исключений с помощью
CustomErrorHandler.GetScript(HttpContext.Current.Response, ex.Message.ToString());
чувствует слоеным и слишком сложен для этого места и может привести к другому исключению. Исключение при обработке другого исключения означает панику. Я бы переместил этот код за пределы. Если вам что-то нужно, пусть это будет простой журнал ошибок log4net и повторите выброс этого исключения.
Если вы читаете только одну БД, нет необходимости в явной транзакции. В соответствии с объектом подключения он не должен быть статичным в любой ситуации и быть создан по требованию. В этом нет никакого штрафа за производительность, поскольку .NET поддерживает пул готовых к использованию соединений и перерабатывает те, которые были «удалены».
Я считаю, что пример всегда лучше, чем просто объяснения, поэтому я хотел бы переустановить ваш код.
public static class reuse
{
static public readonly log4net.ILog log = log4net.LogManager.GetLogger("GeneralLog");
public static void FillDropDownList(string query, string[] parms, DropDownList dropDown)
{
dropDown.Items.Clear();
dropDown.DataSource = GetData(query, parms);
dropDown.DataBind();
}
private static IEnumerable<string> GetData(string query, string[] parms)
{
using (SqlConnection con = new SqlConnection(GetConnString()))
{
try
{
List<string> result = new List<string>();
SqlCommand cmd = new SqlCommand(query, con);
cmd.Parameters.AddRange(parms);
SqlDataReader dr = cmd.ExecuteReader();
if (dr.VisibleFieldCount > 0)
{
while (dr.Read())
result.Add(dr[0].ToString());
}
dr.Close();
return result;
}
catch (Exception ex)
{
log.Error("Exception in GetData()", ex);
throw;
}
}
}
private static string GetConnString()
{
return ConfigurationManager.ConnectionStrings["MyDbConnection"].ConnectionString.ToString(CultureInfo.InvariantCulture);
}
}
У меня есть класс статического соединения, но люди предположили, что он не подходит в параллельной среде. Существует риск внедрения SQL Injection, и я с нетерпением жду использования PetaPoco. Какой тип класса подключения вы предлагаете без ORM? – RKh
@RPK фактическое статическое соединение действительно очень опасно - все, о чем я говорил, это: переместить код, который создает соединение с методом утилиты. Не нужно дублировать это везде. –