2014-10-28 4 views
0

В настоящее время я разрабатываю свои навыки кодирования, практикуя объектно-ориентированное программирование.Работа с несколькими SQL-соединениями

Я работаю с большим количеством SQL-соединений, чтобы получить информацию для инициализации объектов класса. Я считаю, что я плохо себя чувствую, из-за количества SQL-соединений, которые я инициализирую одновременно. Мне часто нужно запускать несколько соединений одновременно, чтобы завершить инициализацию моего основного класса. Ниже приведен краткий пример того, что я имею в виду.

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

public class UserAccount 
{ 
    public long UserId { get; set; } 
    public string UserName { get; set; } 
    public Address UserAddress { get; set;} 
} 
public class UserAddress 
{ 
    public long AddressId { get; set; } 
    public string Address { get; set; } 
} 

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

public static UserAccount GetUserAccountById(long id) 
{ 
    UserAccount result = null; 
    using (SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["connectionString"].ConnectionString)) 
    { 
     using (SqlCommand cmd = new SqlCommand(string.Empty, con)) 
     { 
      cmd.CommandText = "SELECT * FROM UserAccounts WHERE UserId = @Id"; 
      cmd.Parameters.AddWithValue("@Id", id); 
      con.Open(); 
      using (SqlDataReader reader = cmd.ExecuteReader()) 
      { 
       if (reader.Read()) 
        result = RetrieveFromDatabaseRow(reader); 
      } 
      con.Close(); 
     } 
    } 
    return result; 
} 
public static UserAccount RetrieveFromDatabaseRow(SqlDataReader reader) 
{ 
    try 
    { 
     return new UserAccount 
     { 
      UserId = (long)reader["UserId"], 
      UserName = (string)reader["UserName"], 
      UserAddress = UserAddress.GetUserAddressById((long)reader["PrimaryAddressId"]) 
     }; 
    } 
    catch (Exception unhandledException) 
    { 
     GlobalMethods.LogException(unhandledException); 
     return null; 
    } 
} 

Теперь метод UserAddress.GetUserAddressById является почти таким же, как метод экстракции моего первого класса. Он инициализирует соединение и запускает команду SQL.

Почему я думаю, что я делаю это неправильно: текущий способ, которым он выполняется в данный момент, вызывает одновременное открытие нескольких соединений SQL (в моем примере это всего 2, но в моем фактическом проект).

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

Я думал о создании одной глобальной переменной SqlConnection, которая будет инициализирована только один раз, и все мои SQL-запросы будут проходить через него все время, в то же время. Однако я не знаю, как это будет реагировать на такие действия.

Я мог бы использовать некоторые советы и подсказки о том, как правильно выполнить это. Спасибо заранее.

+0

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

+0

@Vajura В этом примере показано, как Я обрабатываю один экземпляр. У меня есть аналогичная функция, которая извлекает всех пользователей из базы данных и добавляет каждую из них в общий список. Однако тот же метод «RetrieveFromDatabaseRow» находится в игре (для инициализации реального объекта User). –

ответ

0

Что вы делаете, похоже на то, что дает Linq, главное отличие в том, что у него нет свойств «Live» для базы данных, но один метод, который внутренне заполняет все свойства за один раз.

Я предлагаю вам внимательно посмотреть на существующую структуру, как Linq к SQL или Linq к Entities (Entity Framework)

+0

Как вы можете видеть в коде, который я предоставил, я использую инструкции «using» каждый раз, когда инициализирую соединение, даже когда я инициализирую команду. Как бы вы предложили работать с глобальным подключением? Учитывая тот факт, что я разрабатываю веб-сайт на основе ASP.NET - где бы я поместил так называемую переменную соединения? –

+0

Да, я не заметил, что все они были на первом месте, исправлено, что – Xyzzy

+0

Приведет этот взгляд, спасибо. –

1

Я думал о том, чтобы один огромном заявлении SQL, который соединяет все необходимые таблицы SQL в одной команде

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

Я думал о том, чтобы один глобальных переменных SqlConnection, которые будут инициализированы только один раз, и все мои запросы SQL будет проходить через него все время, в то же время.

Опять же, не очень хорошая идея. Соединения SQL объединены, поэтому их создание обычно не очень дорого. Кроме того, «глобальные» переменные могут уменьшить тестируемость и добавить зависимости к вашему дизайну, которые нелегко удалить.

Ваш шаблон довольно типичен для низкоуровневого репозитория SQL. Общая картина:

  1. Построить SQL заявление
  2. Создать/открыть соединение
  3. Создайте команду SQL
  4. Выполните команду SQL
  5. Перевести результаты в структуре данных (DataTable/коллекция объектов)
  6. Возврат структура данных

Вы могли возможно rafactor код для того, чтобы некоторого повторного использования, но это примерно так же низко, как вы можете получить, м, так как каждый SQL commandis отличается и может потребовать специальную обработку (параметров, операций и т.д.)

Также , имеющие несколько операторов специального назначения SQL имеет ряд преимуществ, в том числе:

  • эффективность - попросим только для данных, которые необходимы
  • Изоляция - если изменить схему одной таблицы, которую вы только должны изменить команды которые непосредственно затронуты
  • Модульность - это было бы проще, чтобы изменить источник одного объекта, при необходимости

Редактировать на основе комментариев

Это звучит, как вы смотрите на две крайности - один конец тянет друг объект по-разному (10 запросов), а другой тянет все и выбирает вишню, какие данные вы хотите сохранить. Вероятно, есть моменты, когда вы хотите вытащить несколько таблиц за один раз, что легко выполнимо с помощью операторов SQL, не имея одного монолитного оператора SQL, который использует все запросы.

Примером может служить запрос, который объединяет UserAccount и UserAddress, а затем создает несколько объектов из результатов. Это совершенно справедливо и может быть сделано с использованием шаблона, который вы используете, не требуя одного гигантского запроса, чтобы вытащить ВСЕ возможные данные.

ORM, такие как Entity Framework, все время делают это, но когда дело доходит до фактического подключения к базе данных, он использует шаблон, аналогичный тому, что вы используете, - создайте соединение, создайте команду, выполните ее, гидратируйте результаты, закройте соединение.

+0

Итак, что вы предлагаете? Я имею в виду, что вы подытожили то, что я написал на моем главном посту. Как я могу справиться с этой штукой? Что происходит на огромных системах, например, в системе электронной коммерции? Как им удается это сделать? –

+0

Мое предложение состоит в том, чтобы придерживаться шаблона, который у вас есть, или, по крайней мере, не сделать два предложенных вами изменений. Вы только чувствуете, что что-то не так - есть ли у вас какие-то конкретные проблемы, которые вы пытаетесь решить? Где вы видите, что несколько команд открыты одновременно? Почему это проблема? –

+0

Также признайте, что соединения объединены .NET, поэтому создание одного из них, как правило, очень дешевое действие, а множественное соединение _objects_ не обязательно означает множественную фактическую базу данных _connections_. –

Смежные вопросы