Um aplicativo ASP.NET MVC deve usar diretamente o Entity Framework como modelo?


22

Estou criando meu primeiro aplicativo MVC no Visual Studio 2013 (MVC 5) e não sou muito claro sobre a melhor maneira de configurar meu modelo.

Eu gerei um modelo de estrutura de entidade usando primeiro o código de um banco de dados existente. Meu primeiro instinto foi criar algumas classes intermediárias que seriam o modelo usado pelas visualizações e fazer com que essas classes funcionassem com as classes de estrutura da entidade.

Enquanto escrevia as classes intermediárias, percebi que estava apenas reimplementando muitas das coisas que as classes EF já faziam apenas com um setter privado ocasional ou convertido de um tipo de dados para outro. Então isso parecia um desperdício.

A regra geral é usar diretamente as classes da estrutura da entidade como o Modelo para um aplicativo MVC? Ou há algum benefício que estou perdendo por criar essas classes intermediárias?



Se você estava usando o código primeiro, então não havia um banco de dados existente, não?
Isaac Kleinman

1
Com o EF 6.1+, você pode gerar um modelo de primeiro código a partir de um banco de dados existente. Consulte este artigo do MSDN: msdn.microsoft.com/en-au/data/jj200620.aspx
Mike D.

Respostas:


23

Nos meus aplicativos, sempre separei as coisas, com modelos diferentes para o banco de dados (Entity Framework) e MVC. Separei-os em diferentes projetos também:

  • Example.Entities - contém minhas entidades para EF e o contexto do DB para acessá-las.
  • Example.Models - contém modelos MVC.
  • Example.Web - aplicativo da web. Depende de Example.Domain e Example.Models.

Em vez de manter referências a outros objetos, como as entidades do domínio, os modelos MVC mantêm os IDs como números inteiros.

Quando uma solicitação GET para uma página chega, o controlador MVC executa a consulta ao banco de dados, que retorna uma entidade. Eu escrevi métodos "Conversor" que pegam uma entidade de domínio e a convertem em um modelo MVC. Existem outros métodos que fazem o oposto (de um modelo MVC para uma entidade de domínio). O modelo é passado para a visualização e, portanto, para o cliente.

Quando uma solicitação POST é recebida, o controlador MVC obtém um modelo MVC. Um método conversor converte isso em uma entidade de domínio. Esse método também executa validações que não podem ser expressas como atributos e garante que, se a entidade do domínio já existir, estamos atualizando-a em vez de obter uma nova. Os métodos geralmente se parecem com isso:

public class PersonConverter
{
    public MyDatabaseContext _db;

    public PersonEntity Convert(PersonModel source)
    {
         PersonEntity destination = _db.People.Find(source.ID);

         if(destination == null)
             destination = new PersonEntity();

         destination.Name = source.Name;
         destination.Organisation = _db.Organisations.Find(source.OrganisationID);
         //etc

         return destination;
    }

    public PersonModel Convert(PersonEntity source)
    {
         PersonModel destination = new PersonModel()
         {
             Name = source.Name,
             OrganisationID = source.Organisation.ID,
             //etc
         };

         return destination;
    }
}

Usando esses métodos, retiro a duplicação que, de outra forma, ocorreria em cada controlador. O uso de genéricos pode deduplicar as coisas ainda mais.

Fazer as coisas dessa maneira fornece vários benefícios:

  • Você pode personalizar um modelo para uma exibição ou ação específica. Digamos que você tenha um formulário de inscrição para uma pessoa que, quando enviada, cria muitas entidades diferentes (pessoa, organização, endereço). Sem modelos separados de MVC, isso será muito difícil.
  • Se eu precisar passar mais informações para a visualização do que estaria disponível apenas na entidade ou combinar duas entidades em um único modelo, meus preciosos modelos de banco de dados nunca serão tocados.
  • Se você serializar um modelo MVC como JSON ou XML, apenas o modelo imediato será serializado, e nem todas as outras entidades vinculadas a este.

Boa resposta, recomendo usar o ValueInjector ou algo semelhante (pessoalmente, eu odiava o automapper) em vez de mapear manualmente as propriedades de uma classe para outra.
Rocklan

1
Em vez de adicionar uma resposta separada, apenas comentarei aqui que, nas práticas de DDD, seus "conversores" e modelos separados para a exibição seriam considerados parte da Camada de Serviço de Aplicativo. Basicamente, permite que o seu Modelo de Domínio seja tão complexo quanto necessário, enquanto oculta essa complexidade do aplicativo. Ele também impede que o aplicativo precise ser alterado devido a uma alteração no modelo de domínio. O ASL lida com a tradução.
22613 Michael Jackson3 de

Então você faz uma chamada para cada modelo que você possui no seu PersonModel (ou seja, o objeto Organization) para obter as informações desse modelo? Digamos que você tenha um formulário para atualizar as informações da pessoa e da organização. Você receberia uma ligação adicional ao atualizar a Organização? Estou usando procs armazenados, então não posso enviar todos os atributos do modelo e os atributos do modelo que contém todos de uma vez?
luminosa

1
Como você lidaria com o mapeamento de uma coleção? Isso parece ter sido muito mais complicado em EF6 como você pode não apenas criar uma nova lista de entidades com as atualizações como esta apenas re-cria tudo ...
Gerard Wilkinson

2
Em vez de escrever suas próprias classes de conversor, recomendo usar a biblioteca Automapper , que foi escrita para solucionar esse problema. Amadureceu muito desde 2014!
precisa saber é

6

Eu diria que realmente depende da sua aplicação. É apenas um CRUD puro, sem nenhuma lógica de negócios? Então eu usaria modelos EF diretamente em minhas visualizações.

Na maioria das vezes, há pelo menos alguma lógica de negócios envolvida e, em seguida, uma camada entre os modelos de dados / EF e a visualização pode ser uma boa idéia. Nesse caso, pode ser apropriado executar o "CQRS-lite" (veja abaixo) e usar modelos diferentes para entrar e sair do seu controlador. Na maioria das vezes, os modelos de leitura são muito "mais gordos" do que os modelos de gravação ...

No entanto, se o aplicativo contiver muita lógica de negócios e / ou precisar escalar muito, eu implementaria pelo menos o núcleo dele usando CQRS (Segregação de responsabilidade de consulta de comando), DDD (Domain Driven Design) e possivelmente Event Sourcing. O EF pode ser usado como fachada do modelo lido.

Lembre-se também de que você não precisa se ater a uma estratégia / padrão para todo o aplicativo, algumas áreas podem ser CRUD puro e outras podem conter muita lógica de negócios ...

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.