Pergunta

Editar: Eu estou usando SqlDataAdapters para encher os conjuntos de dados. Desculpe - Eu deveria ter sido mais clara

.

Eu estou trabalhando em um projeto onde eu preciso preencher uma série de conjuntos de dados fortemente tipados com informações de procedimentos armazenados. Agora, eu tenho um método genérico em minha camada de acesso a dados:

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

O problema com isso é que eu preciso para estabelecer mapeamentos entre os conjuntos de registros retornado do procedimento armazenado e as tabelas em meus conjuntos de dados. Eu vim com duas opções para fazer isso:

  • Adicionar um novo formal para o meu método FillDataSet (KeyValuePair<string, string>[] mappings), que iria fornecer as informações para os mapeamentos de tabela.
  • Criar um DataSetMappingFactory que levaria um DataSet como um parâmetro e, em seguida, adicione os mapeamentos apropriados com base no seu tipo. Se fosse um tipo desconhecido, então não acrescentaria qualquer mapeamento. Em seguida, ele deve retornar a DataSet ao método FillDataSet.

Algum de vocês tem outros pensamentos sobre como eu poderia abordar este problema? Além disso, Alguém quer pesar sobre uma abordagem que seria melhor em termos de design orientado a objeto?

Foi útil?

Solução

A primeira pergunta que eu ia perguntar é: eu realmente preciso fazer isso em tudo? O designer DataSet digitado já lhe dá uma ferramenta para definir o mapeamento entre um procedimento armazenado e um DataTable. Se você projetar seu DataSet com cuidado, você já tem um método de preenchimento para cada DataTable. Faz sentido de reinventar a roda?

Eu acho que poderia. É muito legal que há uma maneira de manter esse mapeamento, mas tudo em que o mapeamento está congelado em tempo de compilação. Se você quiser alterar o mapeamento, você precisa reconstruir sua montagem. Também o design DataSet digitado não lidar com procedimentos armazenados que retornam vários conjuntos de resultados. Se você deseja mapear genericamente parâmetros e valores, você tem que usar a reflexão para obter as listas de argumentos a partir dos métodos de preenchimento. Pode ser que se você olhar para os fatores (e outros que eu não estou pensando em), que trabalham com a ferramenta existente não é o caminho a percorrer.

Nesse caso, parece-me que o seu objetivo é ser capaz de preencher um DataSet a partir de uma série de procedimentos armazenados com o código que sabe tão pouco quanto possível sobre os detalhes de implementação. Portanto, este é um processo que vai ser conduzido por metadados. Quando você tem um processo conduzido por metadados, o que vai importa mais para você no longo prazo é o quão fácil vai ser para manter os metadados que os usos de processo. Depois de conseguir o trabalho de código, você provavelmente não vai tocá-lo muito. Mas você estará aprimorando os metadados constantemente.

Se eu olhar para o problema a partir dessa perspectiva, a primeira coisa que eu acho que fazer é criar um DataSet digitado para conter os metadados. Isso nos dá um monte de coisas que nós de outra forma tem que descobrir:

  • um formato de persistência
  • um caminho simples para a construção de uma UI limite
  • um caminho igualmente simples para persistindo os metadados em um banco de dados, se decidir ir por esse caminho
  • um modelo de objeto para navegar os dados.

Neste DataSet, você teria uma mesa DataSetType, chaveadas com o tipo de cada digitado DataSet que pretende ser capaz de preencher. Ele teria uma mesa StoredProcedures criança, com uma linha para cada SP que é chamada. Isso teria duas tabelas filho, parâmetros e DataTableType. Não haveria uma linha DataTableType, ordenada por posição ordinal, para cada conjunto de resultados que o SP é esperado para retorno. A tabela DataTableType teria uma mesa ColumnMapping criança. É nesse quadro que você gostaria manter os mapeamentos entre as colunas no conjunto de resultados e as colunas da tabela que você está povoamento.

Certifique-se de todos os seus DataRelations são aninhados, e que você tenha dado nomes racionais para as relações. (I como FK_childtablename_parenttablename.)

Uma vez que você tem isso, o design de classe torna-se bastante simples. A classe tem uma referência para os metadados DataSet, o Connection, etc ,, e expõe um método com esta assinatura:.

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

Você começar usando o tipo do targetDs para encontrar a linha DataSetType de nível superior. Em seguida, todos os métodos privados iterar listas de DataRows retornados por DataTable.GetChildRows (). E você adicionar um evento ou dois para o design de classe, de modo que, uma vez que executa a operação pode gerar eventos para deixar o know aplicativo de chamada como ele está progredindo.

Provavelmente o primeiro lugar que eu esperaria de refatorar este projeto está em me dar mais controle de grão fino sobre o processo de enchimento. Por exemplo, como projetado, há apenas um conjunto de SPs por DataSet digitado. E se eu só quero encher um subconjunto do DataSet? Como projetado, eu não posso. Mas você poderia facilmente fazer a chave primária da tabela DataSetType duas partes, com as peças sendo tipo DataSet e alguns chave string (com um nome como SPSetName, ou OperationName), e adicione a segunda parte da chave para a lista de argumentos FillDataSet .

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top