Eu trabalho em uma empresa que usa apenas procedimentos armazenados para todo o acesso a dados, o que torna muito irritante manter nossos bancos de dados locais sincronizados, a cada confirmação que temos para executar novos procs. Eu usei algumas ORMs básicas no passado e acho a experiência muito melhor e mais limpa. Gostaria de sugerir ao gerente de desenvolvimento e ao restante da equipe que analisemos o uso de um ORM de algum tipo para desenvolvimento futuro (o restante da equipe conhece apenas os procedimentos armazenados e nunca usou mais nada). A arquitetura atual é o .NET 3.5, escrito como o .NET 1.1, com "classes god" que usam uma implementação estranha do ActiveRecord e retornam DataSets não digitados que são repetidos em arquivos code-behind - as classes funcionam da seguinte forma:
class Foo {
public bool LoadFoo() {
bool blnResult = false;
if (this.FooID == 0) {
throw new Exception("FooID must be set before calling this method.");
}
DataSet ds = // ... call to Sproc
if (ds.Tables[0].Rows.Count > 0) {
foo.FooName = ds.Tables[0].Rows[0]["FooName"].ToString();
// other properties set
blnResult = true;
}
return blnResult;
}
}
// Consumer
Foo foo = new Foo();
foo.FooID = 1234;
foo.LoadFoo();
// do stuff with foo...
Não há praticamente nenhuma aplicação de padrões de design. Não há nenhum teste (ninguém mais sabe como escrever testes de unidade, e o teste é feito carregando manualmente o site e bisbilhotando). Examinando nosso banco de dados, temos: 199 tabelas, 13 visualizações, 926 procedimentos armazenados e 93 funções. Cerca de 30 tabelas são usadas para tarefas em lote ou externas, e as demais são usadas em nosso aplicativo principal.
Vale a pena seguir uma abordagem diferente nesse cenário? Estou falando de avançar apenas porque não temos permissão para refatorar o código existente, pois "funciona", portanto não podemos alterar as classes existentes para usar um ORM, mas não sei com que frequência adicionamos novos módulos. de adicionar / corrigir módulos atuais, portanto, não tenho certeza se um ORM é a abordagem correta (muito investido em procedimentos armazenados e DataSets). Se for a escolha certa, como devo apresentar o caso para usar uma? Em primeiro lugar, os únicos benefícios que consigo pensar são em ter um código mais limpo (embora possa não ser, pois a arquitetura atual não é " t construído com ORMs em mente, para que basicamente integrássemos os ORMs para módulos futuros, mas os antigos ainda usariam os DataSets) e menos problemas para lembrar quais scripts de procedimento foram executados e quais precisam ser executados, etc, mas é isso, e eu não sei o quão convincente seria um argumento. A manutenção é outra preocupação, mas que ninguém, exceto eu, parece se preocupar.
fonte
Respostas:
Os procedimentos armazenados são ruins, geralmente são lentos e aproximadamente tão eficientes quanto o código comum do lado do cliente.
[A aceleração geralmente ocorre devido à maneira como o cliente e a interface do procedimento armazenado são projetados e a maneira como as transações são gravadas como breves e focadas explosões de SQL.]
Os procedimentos armazenados são um dos piores lugares para colocar código. Ele divide seu aplicativo em dois idiomas e plataformas, de acordo com regras geralmente aleatórias.
[Esta questão será rebaixada para ter uma pontuação de cerca de -30 porque muitas, muitas pessoas acham que os procedimentos armazenados têm poderes mágicos e devem ser usados apesar dos problemas que causam.]
Mover todo o código do procedimento armazenado para o cliente facilitará as coisas para todos.
Você ainda precisará atualizar o esquema e o modelo ORM de tempos em tempos. No entanto, as alterações de esquema são isoladas das alterações do ORM, permitindo certa independência entre aplicativos e o esquema do banco de dados.
Você poderá testar, corrigir, manter, entender e adaptar todos os procedimentos armazenados à medida que os reescrever. Seu aplicativo será executado da mesma forma e se tornará muito menos frágil porque você não está mais invadindo duas tecnologias diferentes.
ORMs não são mágicos, e boas habilidades de design de banco de dados são absolutamente essenciais para fazê-lo funcionar.
Além disso, os programas com muito SQL do cliente podem ficar lentos devido ao mau pensamento sobre os limites da transação. Um dos motivos pelos quais os procedimentos armazenados parecem ser rápidos é que os procedimentos armazenados forçam um design muito, muito cuidadoso das transações.
ORMs não forçam magicamente o design cuidadoso da transação. O design da transação ainda precisa ser feito com o mesmo cuidado que se fazia ao escrever procedimentos armazenados.
fonte
Os procedimentos armazenados são bons, rápidos e muito eficientes e são o local ideal para colocar seu código relacionado a dados. Mover todo esse código para o cliente tornará as coisas um pouco mais fáceis para você como desenvolvedor do cliente (um pouco, pois você ainda precisará atualizar o esquema e o modelo ORM ao confirmar a alteração), mas perderá todo o código existente e fará seu aplicativo mais lento e provavelmente mais frágil, considerando a perda de todas essas habilidades sql.
Gostaria de saber se os DBAs estão sentados lá dizendo "oh, toda confirmação, eu tenho que desligar o cliente novamente, devemos mover todo o código para os formulários de banco de dados".
No seu caso, você poderá substituir o ORM personalizado existente (ou seja, suas classes engraçadas) por outra pessoa sem nenhuma perda, exceto alterações na maneira como seu código code-behind é escrito. Você também pode manter os SPs, pois a maioria dos ORMs (todos?) Os chamará com prazer. Portanto, eu recomendaria substituir as classes "Foo" por um ORM e partir daí. Eu não recomendaria substituir seus SPs.
PS. Parece que você tem muito código comum nas classes code-behind, o que as torna um padrão de design em si mesmas. o que você acha que é um padrão de design em primeiro lugar! (ok, pode não ser o melhor, ou até bom, mas ainda assim é um DP)
Edit: e agora com o Dapper , qualquer motivo para evitar brigas por um ORM pesado se foi.
fonte
ds.Tables[0].Rows[0]["FooName"].ToString()
porcaria. Manager ama procedimentos armazenados? Ele fica com eles. Mas seria fisicamente impossível argumentar que mover todo esse código repetitivo de clichê para algo gerado por, digamos, LINQ to SQL, era uma coisa ruim.Você parece estar tentando liderar sua equipe de um extremo (procedimentos armazenados e conjuntos de dados) para outro (um ORM completo). Acho que existem outras mudanças mais incrementais que você pode definir sobre a implementação para melhorar a qualidade do código da camada de acesso a dados, que sua equipe pode estar mais disposta a aceitar.
O código de implementação de registro ativo incompleto que você postou não é particularmente elegante - eu recomendo pesquisar o Padrão de Repositório, que é fácil de entender e implementar, e é muito popular entre os desenvolvedores .NET. Esse padrão é frequentemente associado aos ORMs, mas é igualmente fácil criar repositórios usando o ADO.NET simples.
Quanto aos DataSet - eca! Suas bibliotecas de classes serão muito mais fáceis de trabalhar se você retornar objetos digitados estaticamente (ou mesmo dinâmicos). Acredito que esta ilustração explica melhor minha opinião sobre o DataSet.
Além disso, você pode abandonar os procs armazenados sem pular para um ORM - não há nada errado em usar SQL parametrizado. Na verdade, eu definitivamente preferiria usar os proc armazenados, a menos que você tenha procedimentos complexos que economizem em várias viagens de ida e volta ao servidor. Eu também odeio quando abro um banco de dados legado e vejo uma lista interminável de procedimentos CRUD.
Não estou desencorajando o uso de ORMs - geralmente os uso na maioria dos projetos em que trabalho. No entanto, posso ver por que pode haver bastante atrito ao tentar introduzir um neste projeto e sua equipe, para colocar gentilmente, parece que eles pararam de aprender coisas novas há cerca de 8 anos. Dito isto, eu definitivamente daria uma olhada na nova geração de "Micro ORM's", como o Dapper (usado para alimentar este site nem menos) e o Massive , que são incrivelmente fáceis de usar e o mantêm mais próximo do SQL do que um ORM típico, e que sua equipe pode estar mais disposta a aceitar.
fonte
Estou em uma situação semelhante, na verdade nosso hardware, poder e política se inclinam para o lado do banco de dados, então tudo passa por um procedimento armazenado. Infelizmente, eles são um problema para um codificador, especialmente quando se trata de metadados e geração de código, pois não há metadados tão ricos em procedimentos armazenados como tabelas.
Independentemente disso, você ainda pode escrever um código elegante e limpo usando procs armazenados. Atualmente, estou implementando o padrão de repositório com todos os procedimentos armazenados. Sugiro que você procure no FluentAdo.net sua brilhante idéia ao mapear do datareader de volta para seus objetos de negócios. Peguei uma parte dessa ideia e a adaptei novamente para minha solução doméstica.
fonte
JFTR - Sou um desenvolvedor humilde de PHP, mas isso parece uma questão predominantemente política.
Dada a escala da "podridão" que sustenta o aplicativo, então - práticas recomendadas de lado - haveria uma sobrecarga significativa para eliminá-lo. Parece que está na fronteira com a reescrita do território.
Você pode garantir que a alternativa que você sugere traria benefícios para justificar o custo para os negócios? Eu suspeito que o ROI deste empreendimento possa ser difícil de vender para a empresa. A menos que o aplicativo seja instável ou você possa provar o mérito da revisão em termos financeiros - isso pode ser difícil.
O ORM é a única alternativa ao SPROCS? Existem alguns padrões de design entre um ORM completo e o SQL vanilla. Talvez você possa iniciar o processo trazendo esses SPROCS gradualmente para fora do DB em um DBAL. É claro que existe o perigo de que isso se torne um ORM de homebrew ao longo do tempo - mas você teria um passo mais perto do objetivo.
fonte
Mudamos de SP para ORM alguns anos atrás.
Em um caso, tivemos que atualizar 80 tabelas. O antigo modelo de estimativa teria estimado 80 horas para isso com entlib e SP. Fizemos isso em 10 :)
Isso nos proporcionou uma redução de 80% na quantidade de tempo que usamos para desenvolver a camada de acesso a dados.
fonte
Parece-me mais que o problema subjacente é que suas implantações não estão funcionando corretamente e automaticamente.
Pode ser mais fácil configurar um mecanismo de compilação contínuo que saiba como manipular os bancos de dados conforme necessário após cada confirmação.
fonte