2009-09-20 19 views
5

He estado repasando los tutoriales (específicamente los que usan Linq-To-Entities) y entiendo los conceptos básicos, sin embargo, algunas cosas me están dando problemas.¿Mi aplicación ASP.NET MVC está estructurada correctamente?

Los tutoriales generalmente solo incluyen modelos simples y formularios que solo utilizan instrucciones básicas de creación, actualización y eliminación. Los míos son un poco más complicados, y no estoy seguro de estar haciendo esto correctamente porque cuando llega el momento de manejar las relaciones de media docena de objetos de base de datos, los tutoriales dejan de ayudar.

Para el método POST, la forma habitual de realizar operaciones CRUD

entities.AddToTableSet(myClass); 
entities.SaveChanges(); 

no hará lo que yo quiero, porque una clase totalmente implementado no está siendo publicado en el método de controlador. Puedo publicar campos individuales, colecciones de formularios o múltiples objetos DTO y luego llamar a un método en un servicio o repositorio para tomar la información que recibo de una publicación de formulario, junto con la información que necesita para consultar o crearse a sí misma, y ​​luego de todas esas cosas, crea mi objeto de base de datos que puedo guardar.

[AcceptVerbs(HttpVerbs.Post)] 
public ActionResult Add(int id, [Bind(Exclude = "Id")] ClassA classA, 
         [Bind(Exclude = "Id")]ClassB classB) 
{ 
    // Validation occurs here 

    if(!ModelState.IsValid) 
     return View(); 

    try 
    { 
     _someRepositoryOrService.Add(id, classA, classB); 
     return RedirectToAction("Index", new { id = id }); 
    } 
    catch(Exception ex) 
    { 
     // Logging and exception handling occurs here 
    } 
} 


public void Add(int id, ClassA classA, ClassB classB) 
{ 
    EntityA eA = new EntityA 
    { 
     // Set a bunch of properties using the two classes and 
     // whatever queries are needed 
    }; 

    EntityB eB = new EntityB 
    { 
     // Set a bunch of properties using the two classes and 
     // whatever queries are needed 
    }; 

    _entity.AddToEntityASet(eA); 
    _entity.AddToEntityBSet(eB); 
    _entity.SaveChanges(); 
} 

¿Estoy manejando esto correctamente o estoy bastardizando el marco? En realidad, nunca uso un objeto de entidad directamente, cada vez que consulto uno, pongo la información que necesito en un DTO y baso mis Views en eso. Lo mismo ocurre con la creación. ¿Esto está permitido o mi evitación de usar entidades va directamente en contra del propósito de usar el marco?

Editar: Yo también estoy preocupado por este enfoque, ya que requiere constructores vacíos que hacer correctamente las consultas LINQ a causa de este mensaje de error:

Solamente los constructores sin parámetros y inicializadores son compatibles en LINQ a Entidades .

Esto no es un gran problema, ya que rara vez necesito la lógica en los constructores, pero ¿es un problema no tener constructores y solo propiedades públicas?

+1

El objetocontext utilizado por Linq to Entities utiliza la reflexión para crear objetos a partir de la asignación de datos, por lo que es importante y requiere que todas las entidades tengan un constructor sin parámetros para que pueda inicializarse y si desea serializar sus tipos Necesitaré un constructor público también – dmportella

Respuesta

4

_someRepositoryOrService.Add (id, classA, classB);

Yo diría que acoplas tus repositorios con la capa de presentación. Esto no debería ser Tus repositorios solo deberían funcionar con entidades.A continuación, observe cómo su método Add

public void Add (int id, claseA classA, ClassB ClassB)

rompe separación de las preocupaciones (SoC). Se realiza dos tareas:

  1. vista de mapa de datos en entidades
  2. guardar en depósito

Obviamente, el primer paso debe hacerse en la capa de presentación. Considere usar carpetas modelo para esto. También puede ayudarlo a resolver el problema de los constructores, ya que sus carpetas modelo pueden conocer los requisitos de construcción.

Consulte también este excelente post de Jimmy Bogard (coautor de ASP.NET MVC en acción) sobre ViewModels. Esto podría ayudarlo a automatizar el mapeo. También sugiere una técnica invertida: ¡haga que sus controladores trabajen con entidades, no con ViewModels! Los filtros de acción personalizados y los archivos de modelo son realmente la clave para eliminar la rutina que realmente no pertenece a los controladores, sino más bien un detalle de infraestructura entre la vista y el controlador. Por ejemplo, here cómo automatizo la recuperación de entidades. Here's como veo que deben hacer los controladores.

El objetivo aquí es hacer que los controladores contengan la gestión de la lógica empresarial, dejando de lado todos los detalles técnicos que no pertenecen a su negocio. Son restricciones técnicas de las que habla en esta pregunta, y las deja filtrar en su código. Pero puede usar herramientas MVC para mover el nivel de infraestructura hacia ellos.

ACTUALIZACIÓN: No, los repositorios no deben manejar los datos del formulario, eso es lo que quiero decir con "acoplamiento con la presentación". Sí, los repositorios están en el controlador, pero no funcionan con los datos del formulario. Puede (no debería hacerlo) hacer que la forma funcione con "datos de repositorios", es decir, entidades, y eso es lo que hacen la mayoría de los ejemplos, p. NerdDinner, pero no a la inversa. Esto se debe a la regla general: las capas superiores pueden combinarse con las inferiores (presentación combinada con repositorios y entidades), pero nunca el nivel bajo debe estar acoplado a los superiores (las entidades dependen de los repositorios, los repositorios dependen del modelo de formulario, etc.)

El primer paso debe hacerse en el repositorio, eso es correcto, excepto que la asignación de ClassX a EntityX no pertenece a ese paso. Es una preocupación de mapeo: una infraestructura. Véase, por ejemplo, this pregunta sobre el mapeo, pero en general si tiene dos capas (UI y repositorios) no deberían preocuparse por el mapeo, un servicio/ayudante mapeador debería. Además del blog de Jimmy, también puedes leer ASP.NET MVC en acción o simplemente mirar su CodeCampServer para ver cómo hacen mapas con las interfaces IEntityMapper pasadas a los constructores del controlador (ten en cuenta que este es un enfoque más manual y menos laboral que el AutoMapper de Jimmy Bogard).

Una cosa más. Lea sobre el Diseño impulsado por el dominio, busque artículos, aprenda de ellos, pero no tiene que seguir todo. Estas son pautas, no soluciones estrictas. Vea si su proyecto puede manejar eso, vea si puede manejar eso, y así sucesivamente. Intente aplicar estas técnicas, ya que generalmente son las formas excelentes y aprobadas de hacer el desarrollo, pero no las tome a ciegas; es mejor aprender en el camino que aplicar algo que no entiende.

+0

Para acoplar los repositorios, no estoy seguro de lo que quiere decir, tener un repositorio en el controlador parece ser lo que la mayoría de los tutoriales hacen también. En cuanto al primer paso que se realiza en la capa de presentación, ¿no debería hacerse en el repositorio? Pensé que el propósito de los repositorios era preocuparse por manejar los datos del formulario para la conversión de la base de datos. – Brandon

+0

También gracias por los ejemplos y consejos. No he tenido tiempo de hacer los cambios, pero es un buen empujón en la dirección correcta. – Brandon

+0

Ver la actualización. Sugeriría refactorizar lentamente, por ejemplo, primero haga _realEntityRepository.Add (EntityMapper.From (classA)); (o classA.MapToEntity()), luego involucre Custom ModelBinder (que es un gran tema), luego agregue el contenedor IoC (otro gran tema), y así sucesivamente. – queen3

4

Yo diría que usar DTOs y envolver el Entity Framework con sus propios métodos de acceso a datos y capa de negocios es una gran manera de hacerlo. Puede terminar escribiendo mucho código, pero es una mejor arquitectura que pretender que el código generado por Entity Framework es su capa de negocios.

Estos problemas no están necesariamente relacionados necesariamente con ASP.NET MVC. ASP.NET MVC básicamente no brinda ninguna orientación sobre cómo hacer su modelo/acceso a los datos y la mayoría de las muestras y tutoriales para ASP.NET MVC no son implementaciones de modelos dignos de producción, sino solo muestras mínimas.

Parece que estás en el camino correcto, sigue adelante.

Al final, está utilizando Entity Framework principalmente como un generador de código que no genera código muy útil y por lo que es posible que desee buscar en otros generadores de código o herramientas o marcos que se ajusten mejor a sus necesidades.

+0

Realmente estoy usando el framework Entity para probar algo nuevo. Estoy acostumbrado a usar nHibernate. ¿Tiene alguna sugerencia para un mejor generador o marco que debería utilizar? – Brandon

+0

No conozco nada que se ajuste perfectamente a sus necesidades. Algunos de estos son comerciales y algunos son gratuitos. Sin ningún orden en particular: Plantillas T4, CodeSmith, LLBLGen Pro. –

+1

Esta es, en general, una muy buena respuesta (+1), pero no estoy de acuerdo con que esté utilizando Entity Framework como un generador de código. Lo que es mucho más importante es que está usando Entity Framework para mapear su base de datos en espacio de objetos. Esto es importante incluso si nunca materializas un tipo de entidad; todavía usa las entidades de mapeo en sus consultas de LINQ to Entities mientras las proyecta en otros tipos. –

Cuestiones relacionadas