Архитектурный дизайн для проекта с несколькими клиентами с немного отличающейся структурой базы данных (для каждого клиента) - PullRequest
3 голосов
/ 15 марта 2011

Я поддерживаю приложение, которое было скопировано для каждого нового клиента ( ... да, я знаю ).Если новый клиент хотел каких-то новых функций, которые не нужны другим, то изменялась только его часть кода.Решение также включает в себя своего рода «common.dll», в который помещается весь код, одинаковый для всех клиентов.

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

Поскольку «типизированные наборы данных» (ADO.NET C # 2.0) используются в решении Visual Studioдля каждого клиента всегда есть конкретное решение (файл) и в нем конкретный типизированный набор данных (например, «XyDataSet.xsd»).В решениях у меня есть вспомогательные классы, например.для обработки заказов.Одним из методов в этом классе может быть «GetOrder (string orderId)», который использует специфический для клиента DataSet для получения заказа (как типизированный DataRow).

Как вы видите, у меня есть методы «GetOrder» в каждом решениидля каждого клиента, поскольку в таблице заказов могут быть небольшие различия, например, дополнительные столбцы.Поэтому, если необходимо внести изменения в общую функциональность «GetOrder», я должен изменить это во всех проектах, что, конечно, является кошмаром обслуживания.

Кто-нибудь из вас видел, как эта «архитектура» могла бы бытьулучшенный?Или, может быть, при существующих в настоящее время различных схемах БД не так много улучшений на более высоком уровне приложений?

Ответы [ 4 ]

3 голосов
/ 15 марта 2011

Очень сложно ответить на этот вопрос полностью, но я бы начал думать так:

Уровень базы данных:

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

    Orders {OrderID, CustomerID и т. д.} (это таблица владельца)OrderExtensions {ExtensionID, ExtensionName, ExtensionValue} (это таблица расширений для заказов)OrderExtensionsToCustomers {CustomerID, ExtensionID} (показывает, какое расширение доступно для какого клиента)

Уровень уровня доступа к данным:

  • Дизайн уровня базы данных должен бытьреализовано здесь.

Уровень уровня модели домена:

  • Некоторые манипуляции с функциями (для уровня пользовательского интерфейса) должны быть перенесены сюда.

Уровень уровня пользовательского интерфейса:

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

Окончательное изображение:

  • Клиент получает доступ к интерфейсу пользовательского интерфейса, фактически к определенной странице.
  • База данных запрашивает функции пользовательского интерфейса, доступные для текущего клиента (например, дополнительные кнопки и т. Д.).
  • База данных возвращает определения каждой функции для клиента.
  • Каждая функция загружается динамически и добавляется на страницу (например, в специальные заполнители для функций).
  • Когдафункция должна действовать, она передает запрос на уровень домена, который, в свою очередь, загружает «процессорную» часть функции, может быть, также динамически, или просто находит реализацию, которую функция должна вызвать.
  • Call isнаправляется в базу данных, и общая информация сохраняется в общих (владелец) таблицах, а дополнительные (extensio)n) информация сохраняется в других (дополнительных) таблицах.

Я знаю, что это длинный ответ, но я надеюсь, что это имеет смысл: -)

1 голос
/ 15 марта 2011

Создайте типизированный набор данных, который содержит все общие столбцы таблиц, но не специализированные. В соответствующий xsd-файл для каждой таблицы добавьте

  <xs:anyAttribute />

Это позволит загружать столбцы в таблицу данных, которые не определены в наборе данных xsd.

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

Я не уверен, что vs2008 / vs2010 dataset-editor может обработать это или даже уничтожить информацию anyAttribute. Но генератор кода dotnet xsd.exe поддерживает anyAttribute начиная с dotnet 1.0, включая текущую dotnet 4.0

1 голос
/ 15 марта 2011

Во-первых, ай. Жесткий концерт.

Есть много вещей, которые вы могли бы сделать, чтобы перейти на лучшую архитектуру - это зависит от того, сколько времени вы можете потратить на это. Я бы посоветовал прочитать «Рефакторинг на паттерны» Кериевского для идей.

Чтобы ответить на ваш конкретный вопрос - я бы рассмотрел шаблон "метод шаблона". В общем, вы определяете getOrder как последовательность шагов и позволяете подклассам переопределять эти шаги по мере необходимости. http://www.dofactory.com/Patterns/PatternTemplate.aspx

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

Я бы также предложил инвестировать в юнит-тесты, если вы еще этого не сделали.

1 голос
/ 15 марта 2011

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

...