¿Debería una aplicación ASP.NET MVC usar directamente Entity Framework como modelo?

22

Estoy construyendo mi primera aplicación MVC en Visual Studio 2013 (MVC 5) y no estoy seguro de la mejor manera de configurar mi modelo.

He generado un modelo de marco de entidad usando primero el código de una base de datos existente. Mi primer instinto fue crear algunas clases intermedias que serían el modelo utilizado por las vistas y hacer que esas clases funcionen con las clases de marco de entidad.

Mientras escribía las clases intermedias, me di cuenta de que, en su mayoría, solo estaba re-implementando muchas de las cosas que las clases EF ya hacían con el configurador privado ocasional o el envío de un tipo de datos a otro. Entonces eso parecía un desperdicio.

¿Es la regla general usar directamente las clases de marco de entidad como el Modelo para una aplicación MVC? ¿O hay algún beneficio que me falta para construir estas clases intermedias?

Mike D.
fuente
Si estaba usando código primero, entonces no había una base de datos existente, ¿no?
Isaac Kleinman
1
Con EF 6.1+ puede generar un modelo de código primero a partir de una base de datos existente. Vea este artículo de MSDN: msdn.microsoft.com/en-au/data/jj200620.aspx
Mike D.

Respuestas:

23

En mis aplicaciones siempre he separado las cosas, con diferentes modelos para la base de datos (Entity Framework) y MVC. También los he separado en diferentes proyectos:

  • Ejemplo : Entidades: contiene mis entidades para EF y el contexto de DB para acceder a ellas.
  • Ejemplo.Modelos : contiene modelos MVC.
  • Ejemplo.Web - aplicación web. Depende tanto de Example.Domain como Example.Models.

En lugar de contener referencias a otros objetos como lo hacen las entidades de dominio, los modelos MVC contienen ID como enteros.

Cuando entra una solicitud GET para una página, el controlador MVC realiza la consulta de la base de datos, que devuelve una entidad. He escrito métodos "convertidores" que toman una entidad de dominio y la convierten en un modelo MVC. Hay otros métodos que hacen lo contrario (de un modelo MVC a una entidad de dominio). El modelo se pasa a la vista y, por lo tanto, al cliente.

Cuando llega una solicitud POST, el controlador MVC obtiene un modelo MVC. Un método convertidor convierte esto en una entidad de dominio. Este método también realiza cualquier validación que no pueda expresarse como atributos, y asegura que si la entidad de dominio ya existe, la estamos actualizando en lugar de obtener una nueva. Los métodos generalmente se ven así:

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;
    }
}

Al usar estos métodos, elimino la duplicación que de lo contrario ocurriría en cada controlador. El uso de genéricos puede deduplicar las cosas aún más.

Hacer las cosas de esta manera proporciona múltiples beneficios:

  • Puede personalizar un modelo para una vista o acción específica. Supongamos que tiene un formulario de registro para una persona que, cuando se envía, crea muchas entidades diferentes (persona, organización, dirección). Sin modelos MVC separados, esto será muy difícil.
  • Si necesito pasar más información a la vista de la que estaría disponible solo en la entidad, o combinar dos entidades en un solo modelo, entonces mis preciosos modelos de bases de datos nunca se tocan.
  • Si alguna vez serializa un modelo MVC como JSON o XML, solo obtendrá el modelo inmediato que se serializa, no todas las demás entidades vinculadas a este.
Jack Scott
fuente
Buena respuesta, recomendaría usar ValueInjector o algo similar (personalmente odiaba el automapper) en lugar de asignar manualmente propiedades de una clase a otra.
Rocklan
1
En lugar de agregar una respuesta por separado, solo comentaré aquí que en las prácticas DDD, sus "convertidores" y modelos separados para la vista se considerarían parte de la Capa de Servicio de Aplicación. Básicamente, permite que su Modelo de dominio sea tan complejo como sea necesario mientras oculta esa complejidad de la aplicación. También protege la aplicación de tener que cambiarla debido a un cambio en el modelo de dominio. El ASL maneja la traducción.
Michael Brown
¿Entonces hace una llamada para cada modelo que tiene en su PersonModel (es decir, el objeto Organización) para obtener la información de ese modelo? Supongamos que tiene un formulario para actualizar la información de la persona y la organización, ¿tendría una llamada adicional cuando actualice la Organización? Estoy usando procs almacenados, así que ¿no podría enviar todos los atributos del modelo y alguno que contenga los atributos del modelo a la vez?
Luminoso
1
¿Cómo manejarías el mapeo de una colección? Eso parece haber sido mucho más complicado en EF6, ya que ya no puedes simplemente crear una nueva lista de entidades con las actualizaciones, ya que esto simplemente recrea todo ...
Gerard Wilkinson
2
En lugar de escribir sus propias clases de convertidor, recomendaría usar la biblioteca Automapper que se ha escrito para resolver este problema. ¡Ha madurado mucho desde 2014!
BenSmith
6

Yo diría que realmente depende de su aplicación. ¿Es solo hacer CRUD puro, sin ninguna lógica comercial? Entonces usaría los modelos EF directamente en mis vistas.

La mayoría de las veces hay al menos algo de lógica de negocios involucrada y luego una capa entre los modelos de datos / EF y la vista podría ser una buena idea. En este caso, puede ser apropiado hacer "CQRS-lite" (ver más abajo) y usar diferentes modelos dentro y fuera de su controlador. La mayoría de las veces los modelos de lectura son mucho más "gordos" que los de escritura ...

Sin embargo, si la aplicación contiene mucha lógica empresarial y / o necesita escalar mucho, implementaría al menos el núcleo de la misma utilizando CQRS (segmentación de responsabilidad de consulta de comando), DDD (diseño impulsado por dominio) y posiblemente abastecimiento de eventos. Entonces EF podría usarse como la fachada del modelo de lectura.

También recuerde que no necesita apegarse a una estrategia / patrón para toda la aplicación, algunas áreas pueden ser CRUD puro y otras áreas pueden contener mucha lógica comercial ...

jhdrn
fuente