Отображение строго типизированных DataSets в универсальном методе FillDataSet в C # - PullRequest
1 голос
/ 23 октября 2008

Редактировать: Я использую SqlDataAdapters для заполнения наборов данных. Извините - мне следовало быть более ясным.

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

public static DataSet FillDataSet(DataSet dataSet, string storedProcedureName, Dictionary<string, string> parameters);

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

  • Добавьте новый формальный метод в мой FillDataSet (KeyValuePair<string, string>[] mappings), который предоставит информацию для сопоставления таблиц.
  • Создайте DataSetMappingFactory, который будет принимать DataSet в качестве параметра, а затем добавьте соответствующие сопоставления на основе его типа. Если бы это был неизвестный тип, то он не добавил бы никаких отображений. Затем он вернет DataSet методу FillDataSet.

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

1 Ответ

1 голос
/ 24 октября 2008

Первый вопрос, который я хотел бы задать: мне действительно нужно это делать вообще? Типизированный конструктор DataSet уже предоставляет вам инструмент для определения соответствия между хранимой процедурой и DataTable. Если вы тщательно проектируете свой DataSet, у вас уже есть метод Fill для каждого DataTable. Имеет ли смысл изобретать это колесо?

Я думаю, что может. Это действительно здорово, что есть способ сохранить это отображение, но все в этом отображении заморожено во время компиляции. Если вы хотите изменить отображение, вам нужно перестроить сборку. Также типизированный дизайн DataSet не имеет отношения к хранимым процедурам, которые возвращают несколько наборов результатов. Если вы хотите отображать параметры и значения в общем, вы должны использовать отражение, чтобы получить списки аргументов из методов Fill. Может быть, если вы посмотрите на эти факторы (и другие, о которых я не думаю), то работа с существующим инструментом - это не тот путь, по которому нужно идти.

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

Если я посмотрю на проблему с этой точки зрения, первое, что я думаю сделать, - это создать типизированный DataSet, содержащий метаданные. Это дает нам кучу вещей, которые мы иначе должны были бы выяснить:

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

В этом наборе данных у вас будет таблица DataSetType, в которой указан тип каждого набранного набора данных, который вы собираетесь заполнить. Он будет иметь дочернюю таблицу StoredProcedures со строкой для каждого вызываемого SP. Это будет две дочерние таблицы, Parameter и DataTableType. Для каждого набора результатов, который ожидается от SP, должна быть одна строка DataTableType, упорядоченная по порядковому положению. Таблица DataTableType будет иметь дочернюю таблицу ColumnMapping. Именно в этой таблице вы будете поддерживать сопоставления между столбцами в наборе результатов и столбцами в таблице, которую вы заполняете.

Убедитесь, что все ваши DataRelations вложены и что вы дали рациональные имена отношениям. (Мне нравится FK_childtablename_parenttablename.)

Как только вы это сделаете, дизайн класса станет довольно простым. Класс имеет ссылку на метаданные DataSet, Connection и т. Д., И он предоставляет метод с такой подписью:

public void FillDataSet(DataSet targetDs, Dictionary<string, Dictionary<string, KeyValuePair<string, string>> parameterMap);

Вы начинаете с использования Типа targetDs, чтобы найти строку DataSetType верхнего уровня. Затем все частные методы перебирают списки DataRows, возвращаемые DataTable.GetChildRows (). И вы добавляете одно или два события в дизайн класса, чтобы при выполнении операции он мог вызывать события, чтобы сообщить вызывающему приложению, как оно продвигается.

Вероятно, первое место, на которое я рассчитываю провести рефакторинг этого проекта, это дать мне более точный контроль над процессом заполнения. Например, как задумано, есть только один набор SP для каждого типизированного DataSet. Что если я хочу заполнить только подмножество DataSet? Как и задумано, я не могу. Но вы можете легко создать первичный ключ таблицы DataSetType, состоящий из двух частей, с частями типа DataSet и некоторого строкового ключа (с таким именем, как SPSetName или OperationName), и добавить вторую часть ключа в список аргументов FillDataSet .

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