Должен ли я иметь один класс для каждой базы данных, которую я использую? - PullRequest
4 голосов
/ 14 декабря 2008

Во-первых, позвольте мне объяснить, что я делаю. Мне нужно взять заказ, который разделен на разные базы данных, и распечатать этот очень большой заказ. Что мне нужно из заказов - это около 100 столбцов из разных баз данных. То, как я это делал, - это запрос с объединением и присвоение всех значений столбца переменной в моем одном большом классе Order. Это стало проблематичным. Я задаюсь вопросом, вместо того, чтобы иметь один класс, который состоит из приблизительно 100 участников, которые составляют заказ. Должен ли я иметь только один класс для каждой базы данных, которую я использую, и затем работать с этим?

Позвольте мне добавить к этому. По сути, лучше сопоставить ваши объекты с исходными таблицами базы данных или с результирующим набором. Потому что мой объект сопоставлен с набором результатов, а не с отдельными таблицами.

Ответы [ 6 ]

2 голосов
/ 14 декабря 2008

Я бы рекомендовал для этого объектно-ориентированное решение. Предположительно ваша база данных разработана с таблицами, которые представляют логические группы данных. Каждая из этих таблиц, вероятно, может быть сопоставлена ​​с классом в вашей системе, хотя в некоторых случаях это может быть несколько таблиц, составляющих объект, или может быть несколько классов, на которые таблица отображается с использованием подклассов. Если вам нужно отобразить данные из нескольких таблиц - например, список заказов с некоторыми данными от клиента, связанными с заказом - тогда вы можете использовать представления, объединения или хранимые процедуры для создания объекта класса представления, который представляет выбранные данные в представлении / объединение / sp.

По сути, я описываю N-уровневую архитектуру данных, где у вас есть низкоуровневый уровень доступа к данным, который обрабатывает данные с ориентацией SQL - таблицы, представления, хранимые процедуры. Выше этого может быть общий уровень объектов, который имеет дело с общими объектами данных и взаимодействует с уровнем доступа к данным для хранения / извлечения объектов из базы данных. Наконец, над этим у вас есть строго типизированный уровень бизнес-объектов, где ваше приложение работает с классами, которые семантически связаны с вашим приложением - заказами, клиентами, счетами и т. Д. Существует множество различных шаблонов для реализации этого типа общей архитектуры, и вам следует изучить несколько, чтобы увидеть, что подходит вашему приложению нуждается в лучшем. Возможно, вы захотите напрямую использовать объектно-реляционное отображение, такое как LINQ или nHibernate, или вам может потребоваться наложить хранилище поверх ORM.

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

1 голос
/ 14 декабря 2008

Один изящный и простой подход к решению этой проблемы - шаблон Active Record:

http://en.wikipedia.org/wiki/Active_record_pattern

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

1 голос
/ 14 декабря 2008

почему бы просто не загрузить данные из отдельных БД inidividuallly?

Например, ваш конструктор для объекта Order будет выглядеть так:

Method New Order(orderId) {
   Get Database 1 Details
   Load Details into appropriate Variables
   Get Database 2 Details 
   Load Details into appropriate Variables
   Get Database **N** Details 
   Load Details into appropriate Variables
}

упрощает поддержку sql, который касается отдельных БД, и у вас не будет дюжины разных классов для каждой БД.

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

Или вы могли бы упростить и упростить ваше объединение, превратив его в ВИД в одной из ваших баз данных.

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

0 голосов
/ 14 декабря 2008

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

Для бизнес-логики «заказ» - это, как правило, единое связное понятие (по крайней мере, именно так вы начали его формировать). Может ли тот факт, что он отображается в нескольких таблицах (или базах данных) быть артефактом сбора данных? Я хотел бы задать себе эти вопросы, прежде чем разбить его:

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

Если вы не ответите «да» ни на один из этих вопросов, я держу пари, что ваш код будет более простым и более читабельным, если он будет работать только с порядком в качестве атомарного объекта и позволит базе данных скрыть сложность того, где он находится. исходя из (вы могли бы даже использовать представление для этого).

Само по себе количество атрибутов обычно не является причиной для разрушения интерфейса. Но, если сложность (или размер) самого объекта заказа вызывает у вас недостаток, вы можете попытаться упростить его внутренне, чтобы использовать какой-то универсальный метод доступа, такой как:

private object GetOrderAttribute(string attributeName){
    // use a data structure (like a hash table) to store and access internally
}
...
output("Quantity: " + GetOrderAttribute("quantity"));
// etc.

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

0 голосов
/ 14 декабря 2008

Я хотел бы рассмотреть возможность создания класса для обработки данных в каждом отдельном хранилище данных.

Тогда я бы рассмотрел использование шаблона, что-то вроде Фасада для группировки этих подсистем вместе. Ищите в Интернете «Шаблоны проектирования» и «Фасад» для получения дополнительной информации. Затем фасад может учитывать любое конкретное взаимодействие между данными в отдельных хранилищах данных.

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

0 голосов
/ 14 декабря 2008

Это действительно звучит как ваше предпочтение мне. Как бы вы предпочли работать с ним? Будет ли вам легче работать с ним как с отдельными объектами C #, или вам будет легче работать с ним как с несколькими таблицами SQL?

...