DataTable Wrapper или Как отделить пользовательский интерфейс от бизнес-логики - PullRequest
4 голосов
/ 26 марта 2009

Я использую веб-формы, C #, Asp.net. Как мы все знаем, в этой модели пользовательский интерфейс и бизнес-логика часто смешиваются. Как эффективно разделить их?

Пример, который я хотел бы использовать: У меня есть GridView и DataTable (GridView привязывается к DataTable, а DataTable подается из хранимой процедуры).

Я бы хотел, чтобы GridView (UI) и DataTable (бизнес-логика) были развязаны.

Стоит ли писать оболочку для DataTable? Существуют ли практические схемы, которые были доказаны и испытаны, и которые вы могли бы рекомендовать для использования?

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

Мой уровень доступа к базе данных возвращает DataTable. Обратите внимание, что я ДОЛЖЕН использовать этот слой базы данных, так как это политика компании.

Ответы [ 3 ]

2 голосов
/ 26 марта 2009

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

Вы можете увидеть мой прогресс здесь и здесь .

По моему мнению, A DataTable не не представляет бизнес-логику. В частности, это данные, извлекаемые непосредственно из базы данных. Бизнес-логика превращает эти данные в действительно полезный бизнес-объект.

Первый шаг - это отделение DataTable от бизнес-объекта.

Вы можете сделать это, создав объекты и List<object>, которые составляют DataTables и Collections of DataTables, а затем вы можете создать ListView, который отображает эти объекты. Я описываю последние шаги в ссылках, которые я разместил выше. И первые шаги так же просты, как следующие:

  1. Создайте класс, который будет представлять ваш объект.
  2. итерация по вашей DataTable (или DataSet, или как вы извлекаете данные) и вставка этих полей в свойства этого объекта (или этого List<T>);
  3. вернуть этот список в Gridview или ListView для отображения.

Таким образом, ваш ListView или Gridview не будут тесно связаны с методом, которым вы извлекаете ваши данные. Что произойдет, если вы решите получить свои данные из запроса JSON или файла XML позже? Тогда вам придется встроить это туда.

Шаг 1 - Получение данных из базы данных

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

Диаграмма классов

Foo
----
id
Name
Description

А вот и метод:

 private void FillDefault(SqlDataReader reader, Foos foo)
        {
            try
            {
                foo.id = Convert.ToInt32(reader[Foo.Properties.ID]);
                foo.Name = reader[Foo.Properties.NAME].ToString();


             if (!string.IsNullOrEmpty(
                reader[Foo.Properties.DESCRIPTION].ToString()))
                 foo.Description = 
                 reader[Foo.Properties.DESCRIPTION].ToString();
             else foo.Description = string.Empty;
            }
            catch (Exception ex)
            {
               throw new Exception(
               string.Format("Invalid Query. 
               Column '{0}' does not exist in SqlDataReader.", 
               ex.Message));
            }
        }

Как только это произойдет, вы можете вернуть список, пройдя этот процесс в цикле while, который нацелен на функцию SQLDataReader.Read().

Как только вы это сделаете, давайте представим, что ваш Foo, возвращаемый вам, является списком. Если вы сделаете это и перейдете по первой ссылке, которую я дал выше, вы можете заменить Dictionary<TKey, TValue> на List<T> и добиться того же результата (с небольшими отличиями). Класс Properties содержит только имена столбцов в базе данных, поэтому у вас есть одно место для их изменения (на случай, если вам интересно).

DataTable - обновление на основе комментария

Вы всегда можете вставить промежуточный объект. В этом случае я бы вставил бизнес-уровень между DataTable и пользовательским интерфейсом, и я обсудил, что я буду делать выше. Но DataTable не является бизнес-объектом; это визуальное представление базы данных. Вы не можете перенести это на уровень пользовательского интерфейса и назвать его разъединенным. Они говорят, что вы должны использовать DataTable, они говорят, что у вас есть для передачи этого DataTable в пользовательский интерфейс? Я не могу представить, что они будут. Если вы это сделаете, то вы никогда не будете разобщены. Вам всегда понадобится промежуточный объект между DataTable и слоем пользовательского интерфейса.

0 голосов
/ 26 марта 2009

Рассмотрите возможность реализации шаблона MVP (презентатор представления модели). Это дает вам разделение бизнес-логики через интерфейс презентатора, что также позволяет улучшить возможности модульного тестирования. Ваш код за страницей aspx является просто соединителем событий и получателем / установщиком свойств. Вы можете найти его в шаблонах корпоративных приложений и шаблонах MS (CAB - составной блок приложений - если я не ошибаюсь).
Вы можете прочитать больше об этом здесь: http://msdn.microsoft.com/en-us/magazine/cc188690.aspx
Но также предпочтительнее перейти от DataTable / DataSets к объектам (POCO).

0 голосов
/ 26 марта 2009

Я бы начал с отделения таблицы данных прямо в мусорное ведро. Создайте уровень домена, а затем уровень доступа к данным определенного типа, который связан с БД (рекомендуется ORM).

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

...