Criar um número sequencial é simples, mas e se ele tiver que começar de um determinado valor? E se precisar que seja incrementado de outra maneira? Aprenda como fazer!
Utilizar o EF Core facilita muito o processo de desenvolvimento, vamos aprender a configurar uma sequência customizada para evitar configurações extras no BD e deixar mais esta responsabilidade com nossa aplicação.
Neste exemplo vamos supor que possuímos uma classe Pedido e que possui uma propriedade código. Em código nós queremos que esse número inicie em 1000 no banco de dados e que seja incrementado automaticamente de 1 em 1.
O códigos a seguir explicam onde e como fazer esta simples configuração.
Primeiramente configuramos o contexto para criar uma sequencia chamada “MinhaSequencia” que inicia em 1000 e incrementa de 1 em 1.
Na configuração do mapeamento da entidade no EF basta apontar que aquela propriedade vai utilizar uma sequence conhecida:
Basta agora criar a Migration e rodar um “update-database” que estará tudo funcionando perfeitamente.
Vamos continuar a troca de experiências, deixe seu comentário abaixo. Se gostou e concorda com o artigo, compartilhe com seus colegas para transmitirmos o conhecimento para o máximo de pessoas possíveis.
O Entity Framework Core apesar de funcional ainda não está 100%. Algumas funcionalidades requerem workarounds ou simplesmente não existem. Mas temos algo para comemorar, agora podemos trabalhar com tipos complexos sem impactar na modelagem de nossas entidades.
Trabalhando com Tipos Complexos no EF Core
Eu trabalho muito com entidades ricas que seguem as boas práticas de modelagem do DDD. Para possuirmos um domínio rico é necessário dar a maior expressividade possível ao nosso código muitas vezes deixando de usar tipos primitivos para usar tipos complexos.
O Entity Framework Core antes da versão 2 simplesmente não conseguia mapear tipos complexos, ou seja, era necessário impactar diretamente na modelagem de nossas entidades apenas para contornar uma deficiência do ORM. Que coisa horrível não?
Inclusive muitos desenvolvedores simplesmente abriram mão de usar o EF Core e adotaram outras soluções como o Dapper por exemplo. Mas agora esse problema não existe mais!
Mapeando um Tipo Complexo
Vamos supor que sua entidade Cliente possui um campo CPF, muitas vezes basta criar um tipo string e pronto, mas o ideal seria que o CPF fosse um Value Object, pois permite reusabilidade de código além de permitir que a própria classe CPF cuide da questão da validação. Além disso podem existir outros dados como Data de Emissão por exemplo:
Os tipos complexos podem ser Value Objects ou outras entidades, o importante é que o modelo seja o mais rico e expressivo possível.
No EF Core 2 agora é possível utilizar Fluent API de forma nativa (sem gambiarras) e mapear os tipos complexos a partir do recurso OwnsOne:
Depois de todo trabalho de modelagem feito basta executar os comandos:
Add-Migration
Update-Database
E pronto! Seu modelo está criado.
Inserindo e recuperando a entidade através do EF Core
Uma vez que estamos trabalhando com modelos ricos, devemos seguir as boas práticas (utilizar private setters, ad-hoc setters, construtores e validação de consistência):
É necessário criar um construtor protected nas classes para que o EF Core possa recuperar do banco e criar a instância, pois ele não entende o construtor.
As validações foram feitas na mão e lançando exceptions para fins de demonstração
O objeto é recuperado exatamente como se deseja do banco
Testes
Testar é importante certo? Esse projeto foi disponibilizado com o código fonte completo inclusive testando todas as situações previstas:
Com este código fonte eu espero ajudar você a não ter mais nenhum problema de mapeamento de tipos complexos do seu domínio rico com Entity Framework Core.
O EF Core ainda apresenta problemas irritantes como não possuir mapeamento Many to Many. É necessário fazer uma gambiarra horrível (mas funciona).
Não deixe de utilizar modelos ricos em suas aplicações, é muito importante para um bom design de código e uma modelagem correta de seu domínio. Agora o EF Core não será mais um problema.
Caso esteja interessado em conhecer mais sobre Testes, TDD, ASP.NET, DDD, Padrões de Arquitetura e boas práticas de desenvolvimento não deixe de conferir as ementas dos meus cursos:
Vamos continuar a troca de experiências, deixe seu comentário abaixo. Se gostou e concorda com o artigo, compartilhe com seus colegas para transmitirmos o conhecimento para o máximo de pessoas possíveis.
O Equinox Project é um projeto open-source desenvolvido em ASP.NET Core que implementa uma série de tecnologias e abordagens muito utilizadas em grandes projetos.
O Equinox Project é a mais recente contribuição que eu entrego a comunidade técnica e espero que seja de grande ajuda para servir de referência nos futuros projetos escritos em ASP.NET Core.
O Equinox Project (versão 1.0) é o resultado de quase duas semanas de estudos e desenvolvimento que dediquei ao criar uma aplicação funcional implementando diversas tecnologias e abordagens na nova plataforma ASP.NET Core.
Por ser totalmente desenvolvido com .NET Core esta aplicação pode rodar em ambientes Windows, Linux e OSX (Mac).
Tecnologias/Recursos Implementados
ASP.NET Core 1.1 (com .NET Core)
ASP.NET MVC Core
ASP.NET Identity Core
Isolado do MVC e Autenticando via
Facebook ou Cadastro
Entity Framework Core
AutoMapper
.NET Core Native DI (Isolado do MVC)
Unit of Work
Repository e Generic Repository
FluentValidator
Arquitetura
Arquitetura completa com separação de responsabilidades, SOLID e Clean Code
O Equinox Project na versão 1.0 implementa um cadastro de clientes (CRUD) com regras de negócio e validações de dados.
Toda escrita de dados ocorre através de Commands e CommandHandlers que são processados por um Bus em memória (podendo ser adaptado para um Message Queue por exemplo).
Após a execução de um Command é disparado um Evento que realiza alguma ação informativa e também é persistido na base (Event Sourcing).
A leitura de dados ocorre de forma mais simples dispensando algumas camadas de negócio.
Todas as ações são autorizadas pelo mecanismo do ASP.NET Identity que baseia-se em Claims para permitir a leitura e escrita dos dados.
As validações de consistência dos dados são realizadas nos Commands e utilizam o FluentValidator como mecanismo.
Todos os erros no processamento ou na validação dos dados são disparados através de Domain Events/Notifications e são informados ao usuário de forma personalizada.
É possível visualizar a história da entidade através da aplicação que informa desde a criação até a exclusão as mudanças dos dados que ocorreram e o usuário que as executou.
Estes são alguns dos recursos implementados, existem diversos outros em toda extensão da aplicação. Cada um destes recursos eu irei tratar em artigos individuais em uma nova série sobre ASP.NET Core que irei iniciar muito em breve.
Aviso
Este projeto não pretende ser uma solução definitiva para todos os cenários.
Algumas versões utilizadas (inclusive do ASP.NET Core 1.1) estão em Beta ou Pre-Release.
Cuidado ao utilizar este projeto na sua produção. Analise bem os riscos de ser um Early Adopter.
Talvez você não irá precisar de muitos dos recursos implementados, procure evitar o OverEngineering
Sobre o futuro
A versão 2.0 do Equinox Project será uma aplicação bem mais extensa com os recursos a seguir:
Aplicação completa de aluguel (Booking) utilizando Domain Model Pattern, CQRS e Event Sourcing.
ASP.NET Identity trabalhando através de serviços WebAPI com Bearer Token
Novo front-end
Bancos separados para leitura e gravação de dados
Testes de Unidade
Acompanhe os detalhes que serão atualizados no RoadMap do projeto.
Sugestões?
Tem uma boa ideia sobre implementação ou gostaria de ver algo implementado?
Sugestões e críticas serão muito bem vindas!
Por que Equinox?
O Equinócio (Equinox) é um evento astronômico em que o plano do equador da Terra passa pelo centro do Sol. Este evento ocorre duas vezes por ano em torno de 20 de Março e 23 de Setembro. Wikipedia
Equinox é também uma série de publicações (subtítulo: “The Review of Scientific Illuminism”) em forma de livro que serve como o órgão oficial da A∴A∴, uma ordem iniciática fundada por Aleister Crowley Wikipedia
Estamos Online
O projeto está publicado *orgulhosamente* no Microsoft Azure, experimente!
Caso esteja interessado em conhecer mais sobre ASP.NET, DDD, Padrões de Arquitetura como CQRS, Event Sourcing e boas práticas de desenvolvimento não deixe de conferir as ementas dos meus cursos:
Vamos continuar a troca de experiências, deixe seu comentário abaixo. Se gostou e concorda com o artigo, compartilhe com seus colegas para transmitirmos o conhecimento para o máximo de pessoas possíveis.
O ASP.NET Identity é uma ótima solução para a gestão dos usuários em sua aplicação, porém seu design é diretamente acoplado ao ASP.NET MVC e também devemos evitar de utilizar suas referências no domínio da aplicação.
Desacoplando o ASP.NET Identity. Finalmente após muitos pedidos eu consegui colocar a mão na massa e desenvolver um projeto modelo para ser usado como referência.
Como sabemos o ASP.NET Identity depende diretamente do EF (ou outros), Owin e System.Web, logo todas as implementações do ASP.NET Identity ficam de alguma forma acopladas em nossa camada de apresentação. Quando possuímos uma aplicação onde o usuário é uma peça importante no negócio existe a necessidade de representá-lo na camada de domínio, porém é altamente recomendado que a camada de domínio não conheça tecnologias terceiras (Identity, EF, outros).
Como resolver esse problema?
Foi após alguns estudos que cheguei no modelo que considero ser a “melhor abstração possível”, pois para o ASP.NET Identity funcionar na camada de apresentação é obrigatório levar algumas dependências, porém desde que esteja isolado em outra camada já conseguiremos ótimas boas vantagens.
Aviso: Caso você não conheça o ASP.NET Identity, DDD e Injeção de dependência sugiro que comece pelos tutoriais:
Neste tutorial você encontrará as seguintes tecnologias utilizadas
ASP.NET MVC 5
ASP.NET Identity 2
Entity Framework 6
Fluent API
Injeção de Dependência com Simple Injector
Owin
RestSharp para implementação do Twilio API (SMS)
Existem dois grandes objetivos nesta proposta, o primeiro objetivo é a reutilização, pois com um uma única solução (camada) de gestão de usuários é possível atender N aplicações, facilitando o gerenciamento e manutenção.
O segundo objetivo é permitir que a camada de domínio represente o usuário de forma abstraída, logo não existe referência direta do IdentityUser no domínio, porém é possível consultar os dados de usuário e incluir / modificar as informações salvas.
O primeiro passo é abstrair tudo, mover as dependências do Identity para uma camada isolada, depois injetar no MVC os objetos necessários, para essa implementação eu utilizei o Simple Injector, que como o próprio nome diz, é bem simples, rápido e atendeu bem a necessidade.
Com o Identity isolado e injetado devidamente na camada de apresentação (MVC) basta criar uma camada de acesso a dados que irá fornecer meios do domínio consumir dados do usuário de forma abstraída. A grande sacada está no uso correto do Fluent API e claro muita injeção de dependência.
A solução desde modelo não visa atender completamente a filosofia do DDD, pois procurei simplificar o bastante para deixar simples de modificar, por exemplo adicionando uma camada de Application. Portanto quem utilizar esta arquitetura deve estar ciente que algumas coisas a mais ainda precisam ser feitas.
Gostaria de ressaltar também que o template de projeto ASP.NET MVC que o Visual Studio fornece possui vários problemas de design de código. As controllers de Account e Manage do usuário precisaram ser parcialmente re-escritas para atender a injeção do Identity, problemas como mais de um construtor público e utilização do pattern (ou anti pattern?) Service Locator foram encontrados e retirados.
Para quem quiser acompanhar em detalhes técnicos toda a implementação dessa solução eu preparei o vídeo a seguir.
* Assine meu canal no Youtube 🙂
O código fonte desta solução está disponível no GitHub, caso queira propor alguma melhoria faça um Pull Request, será muito bem recebido.
Se você estiver interessado em conhecer mais e aprender como desenvolver aplicações Web com arquitetura baseada em DDD, aplicando os princípios SOLID, diversos Design Patterns e escrevendo testes de unidade inscreva-se em meu curso:
Vamos continuar a troca de experiências, deixe seu comentário abaixo, se gostou e concorda com o artigo compartilhe com seus colegas para transmitirmos o conhecimento para o máximo de pessoas possíveis.
Vivemos um novo momento no desenvolvimento de software onde a abstração do relacionamento da aplicação com o banco de dados tende a ser cada vez maior, hoje o banco de dados não é mais o centro da aplicação.
Este é um assunto muito polêmico e que interessa tanto aos desenvolvedores de software como aos especialistas em banco de dados (DBA’s e etc).
Quem desenvolve software a mais de 5 anos pôde acompanhar uma nova tendência crescendo rapidamente, que é a forma na qual a aplicação se relaciona com o banco de dados. Infelizmente ainda hoje os profissionais aprendem na faculdade ou no ambiente de trabalho um modelo de desenvolvimento que já está no passado, e é esta minha motivação em escrever este artigo.
Há muitos anos nosso processo de desenvolvimento vem ocorrendo de uma maneira clássica (e hoje em dia inadequada), o DBA desenvolve toda a modelagem do banco de dados elencando as entidades (tabelas) e seus relacionamentos conforme a necessidade e seu próprio entendimento do negócio, após isso aplicam-se as regras de normalização, valida-se o MER (modelo-entidade-relacional) e pronto! Basta escrever as Stored Procedures, Triggers e Views com as regras de negócio e entregar para o desenvolvedor desenvolver a aplicação que vai consumir o banco.
Então a aplicação é uma camada “casca” que envolve o banco de dados, consumindo e inserindo novas informações?
Isso parece meio ridículo para um desenvolvedor de software hoje em dia, mas esse modelo “3 camadas” já foi muito (e ainda é) pregado e defendido por ai. A primeira camada é a UI (user interface) a segunda é o “core” da aplicação que consome diretamente o banco de dados e a terceira é o próprio banco.
Um dos pontos muito defendidos nessa distribuição de 3 camadas era que a máquina do usuário não precisava possuir muito recurso computacional e nem conhecer as regras de negócio uma vez que poderia haver uma engenharia reversa da aplicação instalada.
Esse argumento não é mais válido hoje em dia dado a infinidade de recursos computacionais e tecnológicos que possuímos (Web, SOA, etc.).
Um outro forte argumento para a centralização no banco de dados é de que o servidor de banco de dados é uma máquina muito rica em recursos computacionais e consegue processar as regras de negócio com mais velocidade do que um servidor de aplicação.
Esse argumento além de passado ocasiona diversos problemas que serão abordados a seguir.
Regras de negócio em Stored Procedures é uma má prática
Poderia elencar diversos adjetivos para a utilização de regras de negócios em stored procedures, porém vamos considerar apenas uma má prática que deve ser evitada a todo custo. Listarei alguns problemas/dificuldades muito frequentes com a adoção desta prática:
A linguagem TSQL (Transact SQL) é muito limitada em comparação as linguagens atuais, requer mais código e dificulta a interpretação/entendimento, requer mais esforço aumentando o tempo de codificação.
É muito difícil escrever testes de unidade para regras de negócio em stored procedures.
O mecanismo que gera o plano de execução para as stored procedures não trabalha bem com condições (IF, Case, etc) podendo ocasionar uma lentidão muito grande ao chamar uma stored procedure com diversos fluxos.
Quebra o conceito de responsabilidade única, a regra pode estar parte no banco, parte na stored procedure. Além de aumentar o esforço na analise e detecção de problemas.
Estimula a escrita de milhares de linhas de código em apenas uma store procedure, algumas delas com mais de 4.000 linhas são bem fáceis de se encontrar por ai. O esforço de manutenção é centenas de vezes maior, além do risco de introdução de novos bugs.
Existem diversos contras além dos listados, porém estes citados são base de muitos problemas comuns no dia a dia. Não entenda que as stored procedures não devem ser utilizadas, até devem dependendo do cenário, porém sem regras de negócio.
E sobre o uso das Triggers?
Dentre um determinado conjunto de decisões que podem ocasionar sérios problemas entre aplicação e banco de dados, uma delas é o uso de Triggers.
Triggers podem ser úteis em alguns cenários, porém existem outras opções mais eficazes. Não há nada que uma trigger faça que não possa ser substituído por outro recurso (externo do controle do banco de dados) e que funcione de forma mais controlada, elegante, e lógico, testável.
O servidor de banco de dados é muito mais rápido que o servidor de aplicação
Fato! E deve ser mesmo, pois a questão é, quantos bancos de dados é possível escalar lado a lado? Manter bancos de dados sincronizados não é uma tarefa simples e não custa nada barato. Na maioria das aplicações existe um único banco de dados ativo (outros de contingência) e N servidores de aplicação consumindo o mesmo banco. É muito mais fácil escalar o servidor de aplicação e muito mais barato (basta conferir os valores de licenciamento de um SGBD). A própria aplicação de atualizações nos servidores de aplicação é muito mais simples do que no servidor de banco de dados.
Não é por que o banco de dados tem capacidade computacional superior que ele deve ser responsável pelo negócio em si, o banco de dados é um repositório de dados, ele deve ter alta disponibilidade para entregar com a maior velocidade possível as consultas. Utilizar os recursos computacionais do banco de dados para validar o negócio é queimar dinheiro e ocasionar problemas de performance.
O mundo é muito maior que o relacionamento entre tabelas no banco de dados
Podemos dizer que hoje o modelo de programação orientada a objetos dominou o mercado de software, sim existem ainda outros modelos (procedural, funcional, etc) porém a grande parte do mercado aderiu a famosa OOP.
Programar orientado a objetos é uma forma muito mais rica de mapear o mundo real do que as simples formas de relacionamento presentes de banco de dados relacionais, existem bancos de dados NoSQL, orientados a objetos, baseados em grafos e etc, porém não são populares como os relacionais (MSSQL, Oracle, MySQL, etc).
Se a orientação a objetos é uma forma de mapeamento mais rica que o modelo entidade-relacionamento dos bancos de dados, deveríamos então modelar nossa aplicação baseadas em classes e não em tabelas? Exato!
Partindo desta decisão como ficaria o relacionamento de uma aplicação orientada a objetos consumindo um banco de dados relacional?
Alguém já resolveu esse problema faz muitos anos, são os famosos ORM’s
O ORM (Object-relational mapping) faz justamente este trabalho, mapeando entidades de software (classes) para entidades de bancos de dados (tabelas). Com isto é possível que uma única tabela de banco de dados seja representada por N classes e vice-versa.
Os ORM’s abstraem o banco de dados
Abstrair o banco de dados significa parar de se preocupar com a modelagem do banco na hora de modelar o sistema, a modelagem pode ser feita em UML utilizando diagramas de classes entre outros diversos tipos de diagramas, no final o mapeamento das suas entidades de software estarão muito melhores definidas do que se tivessem sido feitas com base no MER de banco de dados relacionais.
O ORM cuida para que o seu mapeamento orientado a objetos faça sentido com o mapeamento entidade relacionamento.
A abstração não para por ai, através dos ORM’s é possível desligar a dependência tecnológica do banco de dados na aplicação, a aplicação não estará mais acoplada a uma tecnologia de banco de dados, trocar um banco de dados de uma aplicação não é nada trivial, porém se abstrairmos/desacoplarmos a aplicação do banco através do uso de um ORM essa tarefa seria infinitamente mais fácil.
Produtividade! Desenvolvedores não precisam codificar todas as consultas em linguagem TSQL, o ORM promove um novo modelo de consumo do banco de dados, o ORM fica encarregado de gerar as queries para comunicar-se com o banco, quando necessário o desenvolvedor pode fornecer uma query específica para ser utilizada no banco através do ORM.
Escreva sua aplicação e ganhe banco de dados
O modelo Code First já está presente faz alguns anos no mercado e seu uso vem crescendo de forma gigantesca, uma vez que possuímos o ORM para abstrair o banco de dados, por que não deixar com ele também a criação e atualização do banco?
Isso mesmo, basta mapear todo seu universo do negócio em classes, escrevê-las e no final gerar o banco de dados que se adeque a modelagem da aplicação. Afinal o banco de dados é um repositório de dados.
O Entity Framework em sua nova versão (7) trabalhará apenas com o modelo Code First, para desenvolvimento de aplicações com base de dados já existentes será possível utilizar os recursos de engenharia reversa. A atualização do banco pode ser feita também através de recursos como Migrations.
E o DBA? Morreu?
Muito pelo contrário! Quem vai garantir o perfeito funcionamento do banco? Backup, segurança, implementações de recursos de performance, acompanhar problemas em tempo real e prover rápidas soluções, dividir tabelas especiais em discos independentes e etc… Isso tudo é trabalho do DBA.
Uma coisa que está errada faz muito tempo é que a modelagem de banco de dados é de responsabilidade do DBA, criar mais um campo na tabela, escrever uma stored procedure e outras atividades desse tipo eram de decisão do DBA. Quantas vezes um desenvolvedor já precisou explicar para o DBA o por que precisava de um campo a mais numa tabela, ou por que uma stored procedure devia ser alterada. Isso não faz sentido.
Em um time de desenvolvimento o número de DBA’s é muito menor do que o número de desenvolvedores, nesse cenário o DBA iria trabalhar apenas para atender as necessidades dos desenvolvedores, deixar estas responsabilidades com o DBA é impedir de que ele faça seu real trabalho que é manter o banco de dados altamente disponível utilizando todo seu potencial.
Alguns DBA’s são contra o uso de ORM’s por que ferem seu sentimento de responsabilidade por algo que não deveria ser de sua responsabilidade. Os ORM’s aos poucos estão dando de volta aos desenvolvedores o que era para ser seu desde sempre, o domínio da modelagem e desenvolvimento da aplicação. E claro, numa situação de dúvida não custa nada perguntar a opinião do DBA.
Não importa onde estão os dados
Hoje os bancos de dados relacionais não são a única fonte de dados, os dados podem estar disponíveis através do consumo de serviços (SOA, WCF, WebAPI), podem estar em bancos NoSQL (MongoDB, Redis, etc), podem estar em bancos de dados In-Memory (Hekaton, MemSQL) ou simplesmente sendo abstraídos pelo seu ORM.
Por exemplo no DDD (Domain-Driven-Design) temos uma abstração tão grande que realmente não importa de onde vem os dados, a aplicação não fica dependente disto (apenas na camada de configuração de dados). É neste sentido que devemos caminhar, escrever aplicações focadas no domínio do negócio, que por si próprias saibam resolver qualquer problema e que possam ser expostas através de serviços para que sejam consumidas através de qualquer plataforma, device e etc…
Hoje todo gestor de desenvolvimento fala e se interessa por métodos ágeis, não existe agilidade sem teste, testes de unidade e testes de integração, abstrair o banco de dados é uma forma de promover a possibilidade dos testes, da análise do código escrito, da validação da regra de negócio, poder realizar um Mock de um repositório sem bater no banco de dados e etc. Num mundo onde dependemos de um banco de dados presente para realizar um teste de unidade, com certeza esse não é um mundo muito ágil.
Os banco de dados relacionais irão tornar-se obsoletos no futuro?
Essa mesma pergunta foi feita quando surgiram os bancos de dados orientados a objetos, bancos de dados de grafos, NoSQL.
Os bancos de dados relacionais estão acompanhando a evolução tecnológica, tornando-se cada vez mais performáticos, com mais recursos para alta disponibilidade e etc, porém de outro lado estão surgindo conceitos como Big Data que impulsiona a utilização de bancos NoSQL, redes sociais que utilizam muito o conceito de banco de dados de grafos, entre diversas novidades que não param de surgir.
Acredito que cada modelo de aplicação possui um tipo (ou tipos) de banco de dados que melhor atendem o cenário. O importante é saber como e quando utilizar cada um deles.
Para finalizar
O mundo muda constantemente e cada vez mais rápido, conceitos aprendidos na faculdade anos atrás ou até mesmo hoje em dia podem estar em constante desuso. Políticas antigas de empresas ou até mesmo profissionais conservadores de padrões ultrapassados são muito comuns no nosso mercado.
É importante estar antenado e preparado para quebrar paradigmas, pesquisar e aprofundar-se em melhores práticas de desenvolvimento de software, sempre prezando reusabilidade, performance, escalabilidade e com certeza qualidade garantida por testes de unidade.
Além deste artigo eu participei de um bate papo muito construtivo sobre este assunto com meus colegas do AspNetCast, assista o vídeo também.
* Assine meu canal no Youtube
Vamos continuar a troca de conhecimentos, deixe seu comentário abaixo, pode ser dúvida, elogio ou sua opinião que é sempre muito importante 😉
Utilizar o Entity Framework com Code-First a partir de uma base existente é possível e relativamente fácil, inclusive melhorando a nomenclatura da base.
Neste vídeo tutorial iremos acompanhar como funciona o processo de criação de um sistema novo partindo de uma base já existente e utilizando Entity Framework no modelo Code-First.
Como apresentado no vídeo os modelos guiados por design e que geram EDMX estão obsoletos, geram muita dificuldade na manutenção e não serão mais suportados na próxima versão do Entity Framework (7).
Neste tutorial iremos aprender:
Diferenças entre Model-First, Database-First e Code-First.
Instalar o EF Power Tools.
Customização de templates T4 para geração de classes.
Fazer engenharia reversa do banco criando classes POCO e mapeamentos com Fluent API.
Melhorar a nomenclatura das classes e mapeamentos quando o banco de dados não possui padronização ou está num padrão não apropriado para nomenclatura das entidades na aplicação.
Atualizar o banco de dados com Migrations
Como atualizar o código quando houver alteração direta no banco de dados.
Resolver problemas comuns do processo de engenharia reversa.
Vídeo
* Assine meu canal no Youtube 🙂
Vamos continuar com a troca de experiências, deixe seu comentário abaixo.
O ASP.NET Identity possui um padrão de nomenclatura para suas tabelas e campos, muitas vezes é necessário customizar este padrão para atender as necessidades da aplicação, confira como é simples realizar esta tarefa.
Como apresentado aqui algumas vezes, o ASP.NET Identity é um componente muito completo e simples de customizar, ele é escrito baseado no conceito Code-First e sua arquitetura é bem aberta possibilitando a customização de funcionalidades, comportamentos e até mesmo fonte de dados.
As tabelas que o ASP.NET Identity cria automaticamente segue o mesmo processo de qualquer desenvolvimento Code-First, permitindo que o desenvolvedor mapeie na configuração do DbContext toda a modelagem da base que será criada.
Vamos abordar de forma muito simples e pontual como realizar este processo partindo do pré-suposto que sua aplicação foi criada com base no template de aplicação ASP.NET MVC já com o ASP.NET Identity configurado. Independente deste fato, o que é realmente necessário fazer é editar o contexto do ASP.NET Identity.
Uma dica válida para qualquer situação é manter sempre o contexto do ASP.NET Identity separado do contexto da aplicação.
Iremos trabalhar também com a hipótese de customização do IdentityUser através de sua classe derivada ApplicationUser. Vamos ao código.
public class ApplicationUser : IdentityUser
{
public string Apelido { get; set; }
}
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("DefaultConnection")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<IdentityUser>()
.ToTable("Usuarios")
.Property(p => p.Id)
.HasColumnName("UsuarioId");
modelBuilder.Entity<ApplicationUser>()
.ToTable("Usuarios")
.Property(p => p.Id)
.HasColumnName("UsuarioId");
modelBuilder.Entity<IdentityUserRole>()
.ToTable("UsuarioPapel");
modelBuilder.Entity<IdentityUserLogin>()
.ToTable("Logins");
modelBuilder.Entity<IdentityUserClaim>()
.ToTable("Claims");
modelBuilder.Entity<IdentityRole>()
.ToTable("Papeis");
}
}
Na classe ApplicationUser realizamos uma pequena customização adicionando um novo campo (Apelido), apenas para enfatizar a situação.
Na classe ApplicationDbContext repare que ela herda de IdentityDbContext, que é a real classe de contexto do ASP.NET Identity onde ela internamente herda de DbContext.
A ideia de existir a classe ApplicationDbContext é justamente fornecer um contexto para customização, uma vez que a classe IdentityDbContext faz parte dos assemblies do ASP.NET Identity e não é possível ser alterada.
Baseado no conceito da herança o que basicamente fizemos foi sobrescrever o método OnModelCreating da classe base para alterarmos os padrões de nomenclatura. Utilizamos Fluent API para realizar esse mapeamento trocando os nomes das tabelas e campos.
Essa troca não impacta no funcionamento interno do ASP.NET Identity, pois as classes internas permanecem intactas, apenas o mapeamento do modelo objeto / relacional foi modificado e a aplicação irá seguir o que a modelagem manda.
Repare que as duas classes (IdentityUser, ApplicationUser) foram mapeadas para mesma tabela, pois só assim seria possível mapear a classe de usuários e ao mesmo tempo aplicar as customizações, no final tudo vira uma única tabela com informações de ambas as classes.
Detalhes adicionais
É possível utilizar todos os recursos do Fluent API nessa abordagem, sendo possível modificar tipo dos campos, inserir índices, criar novos relacionamentos, mapear novas tabelas e etc.
É possível realizar todo este mapeamento em uma outra classe e configurar esta classe no contexto (assim como fazemos com as nossas entidades no Fluent API).
Simples?
Agora é possível incorporar o ASP.NET Identity ao seu modelo já existente de base de usuários, a única premissa é que todas as tabelas e campos do ASP.NET Identity sejam representados (mapeados) de alguma forma no banco de dados existente.
Vamos continuar a enriquecer este artigo participando nos comentários abaixo com dúvidas, complementos e feedbacks.
Arquitetura de Sistemas Corporativos é um tema muito menos explorado do que ASP.NET MVC 5 e nem por isso é menos importante (na verdade é bem mais), neste vídeo tutorial eu mostrarei como criar uma arquitetura padrão DDD utilizando ASP.NET MVC 5.2, Entity Framework, AutoMapper, IoC com Ninject e muitas dicas para criar uma arquitetura modelo e totalmente responsável.
Como poderão acompanhar nos slides e no vídeo ASP.NET MVC é apenas a ponta do iceberg em uma aplicação corporativa. Quando entramos no mundo real os exemplos dos artigos de sites e livros não nos atendem mais e é necessário buscar mais conhecimento para criar uma aplicação robusta, responsável, testável, escalável e de fácil manutenção.
O modelo DDD (Domain Driven Design) atende muito bem cenários de aplicações corporativas e eu utilizo muito em meus projetos profissionais e pessoais.
Neste vídeo tutorial você aprenderá
Criar uma solução padrão DDD
Separar a aplicação em camadas
Entidades de Domínio
Classes de Serviço
Criar Contratos (Interfaces)
Repositório Genérico
Repositório Especializado
Criar um Contexto do Entity Framework
Trabalhar com Migrations
Criar novas convenções do Entity Framework
Remover algumas convenções do Entity Framework
Sobrescrever o método SaveChanges para persistência de dados
Programar com CodeFirst
Utilizar FluentAPI para modelar tabelas
Criar Relacionamentos entre Entidades e refletindo nas tabelas do banco de dados.
Criar e utilizar a camada de Application
Trabalhar com classes genéricas de Entidades
Abstrair camadas com Injeção de Dependência (IoC)
Implementar o Ninject como container de IoC (DI)
Utilizar ViewModels
Utilizar DataAnnotations para validação de formulários
Mapear ViewModels x Entidade de Domínio com AutoMapper
Muitas dicas para acelerar sua produção
Este conteúdo é aplicado no meu curso de ASP.NET MVC 5 – Enterprise Applications com uma carga horária de 16 horas, com todo o embasamento teórico, técnico e prático, muitos outros patterns, testes, mocks, serviços REST, manipulação de filtros do ASP.NET MVC e etc são abordados no curso para uma preparação completa do futuro arquiteto desenvolvedor.
SLIDES
VÍDEO (3h00 de duração)
* Assine meu canal no Youtube 🙂
SOURCE
Para download do projeto clique aqui (logo será transferido para o GitHub)
Ao executar o comando update-database via Migrations do EF CodeFirst para atualizar um database hospedado no SQL Azure você pode receber uma mensagem de erro:
Tables without a clustered index are not supported in this version of SQL Server. Please create a clustered index and try again.
Pesquisando sobre o erro descobri que é um bug já reportado do EF 6 Alfa 3.
O motivo apresentado por Andrew Peters (EF Developer) foi:
This causes Migrations not to work on Azure because the history table needs at least one clustered PK
Como resolver:
1- Atualize a versão da biblioteca do EF 6 (a correção foi disponibilizada em 07/03/2013).
2 -Caso não seja possível a atualização da biblioteca, existe um workaround:
Crie uma classe de custom migration SQL generator
using System.Data.Entity.Migrations.Model;
using System.Data.Entity.Migrations.Sql;
public class AzureSqlGenerator : SqlServerMigrationSqlGenerator
{
protected override void Generate(CreateTableOperation createTableOperation)
{
if ((createTableOperation.PrimaryKey != null)
&& !createTableOperation.PrimaryKey.IsClustered)
{
createTableOperation.PrimaryKey.IsClustered = true;
}
base.Generate(createTableOperation);
}
}
E registre a sua custom generator no arquivo Configuration.cs da pasta Migrations
internal sealed class Configuration : DbMigrationsConfiguration<MyContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = true;
// Esta linha abaixo:
SetSqlGenerator("System.Data.SqlClient", new AzureSqlGenerator());
}
protected override void Seed(MyContext context)
{
}
}
Pronto!
Pode rodar novamente o comando update-database que o problema estará resolvido.
Olá pessoal, O que é POCO? O que seria uma classe POCO?
Hoje em dia utilizar um ORM como Entity Framework ou NHibernate é bem comum, aplicar conceitos do DDD também vem sido bem abordados e discutidos e em todas essas abordagens acaba surgindo o uso de POCO. Afinal o que é POCO?
Tentar decifrar esse nome vai ser bem difícil, POCO significa Plain OLD CLR Object, tentando traduzir isso eu gosto de chamar POCO de “Bom e velho objeto do CLR”.
POCO é um acrônimo de POJO Plain OLD Java Object, criado por Martin Fowler (um expert em OOP) como ele vem de Java acabou dando esse nome, então os especialistas em .Net fizeram uma pequena mudança para trazer esse conceito ao nosso mundo e surgiu o POCO (mas é o mesmo conceito, não muda nada).
Legal, mas ainda não entendi o que é POCO?
É fácil de entender, POCO é uma classe que segue o ideal do OOP, pois tem estado e comportamento, porém não depende e não conhece nenhum recurso externo além do Framework .Net.
Uma classe POCO é utilizada como classe de domínio (negócio) da sua aplicação, o que chamo de Modelo de Domínio. Um Modelo de Domínio é formado pelas classes que compõem a estrutura de negócio do mundo real.
Nós não desenvolvemos sistemas apenas baseados no Framework .Net, quase sempre necessitamos de uma ferramenta externa, por exemplo um ORM, que por sua vez impõe o uso de referências como classes, interfaces, decorações nos métodos etc…
Construir uma classe POCO é escrever uma classe que contenha atributos, construtores e métodos mas que não dependam de nada mais do que o próprio .Net Framework forneça.
Quem já utilizou o Entity Framework na forma Database First já viu como que fica a bagunça de uma classe? Acabamos gerando um único arquivo EDMX com muitas dependências, herdando de um objeto ObjectContext. Geralmente esse código é bastante poluído e dificíl de estender.
[EdmEntityTypeAttribute(NamespaceName="SistemaOS.Model", Name="Pessoas")]
[Serializable()]
[DataContractAttribute(IsReference=true)]
public partial class Pessoas : EntityObject
{
[EdmScalarPropertyAttribute(EntityKeyProperty=true, IsNullable=false)]
[DataMemberAttribute()]
public global::System.Int32 id_pessoa
{
get
{
return _id_pessoa;
}
set
{
if (_id_pessoa != value)
{
Onid_pessoaChanging(value);
ReportPropertyChanging("id_pessoa");
_id_pessoa = StructuralObject.SetValidValue(value, "id_pessoa");
ReportPropertyChanged("id_pessoa");
Onid_pessoaChanged();
}
}
}
}
Ou seja, estamos amarrados ao Entity Framework se deixarmos ele criar nossas classes de entidades.
Um exemplo simples de classe POCO:
public class Pessoa
{
public string Nome { get; set; }
public string Sobrenome { get; set; }
public int Cpf { get; set; }
public string NomeCompleto()
{
return Nome + " " + Sobrenome;
}
}
Veja que neste exemplo não dependemos de nada, é apenas uma classe, tratando de DDD o nosso domínio não pode depender de tecnologia, afinal a minha camada de domínio pode ser adaptada a um outro sistema que não utilizará o Entity Framework e tudo bem! Afinal minha classe POCO não depende disso.
Acredito que a vantagem de usar POCO é exatamente essa, podemos modelar nossas classes de domínio e portá-las para onde quiser, sem a dependência de nenhuma ferramenta externa.
Por isso recomendo que utilizem ferramentas que dê suporte a POCO, e isso não é difícil, por exemplo Entity Framework, NHibernate, WCF permitem trabalhar com POCO.
No Entity Framework, por exemplo, podemos trabalhar da forma Code First, ou seja, escrevemos primeiro classes POCO e no final a modelagem da base de dados é criada conforme a modelagem do nosso domínio.
Então uma classe POCO é uma classe anêmica?
– Não! Uma classe anêmica pode até ser uma classe POCO, mas nada diz que uma classe POCO deve ser anêmica, afinal ela pode possuir atributos e métodos.
Uma classe anêmica não possui métodos, e por alguns é considerada um anti-pattern, pois fere o conceito de orientação a objeto, mas isso é assunto para um outro artigo. 🙂
Uma classe POCO é como se fosse uma DTO então?
– Não! Uma DTO “Data Transfer Object” é outra coisa, pense em DTO como uma “sacola de dados”, ou seja, em um objeto DTO podemos ter dados das classes Pessoa, Endereço, Empresa.
DTO é um outro pattern desenhado justamente para reduzir o número de chamadas e a quantidade de dados necessários para trafegar entre camadas de sistemas, por exemplo, entre uma aplicação web e um serviço.
Uma classe POCO é sua classe de domínio e um DTO é o objeto para transitar dados apenas, podem possuir dados de mais de uma entidade e não possuem métodos, portanto não é POCO.
Se minha classe herda de uma classe base então não tenho uma classe POCO?
– Depende, desde que a classe base não tenha nenhuma dependência com outras camadas da aplicação e ferramentas externas, ainda é uma classe POCO.