practices pattern mvc framework example best c# dto llblgenpro business-logic-layer

c# - pattern - dto php



Cómo diseñar objetos de transferencia de datos en Business Logic Layer (2)

DTO

Estoy construyendo una aplicación web que me gustaría escalar para muchos usuarios. Además, debo exponer la funcionalidad a terceros de confianza a través de los servicios web.

Estoy usando LLBLGen para generar la capa de acceso a datos (usando SQL Server 2008). El objetivo es crear una capa de lógica de negocios que proteja a la aplicación web de los detalles de DAL y, por supuesto, brinde un nivel extra de validación más allá del DAL. Además, por lo que puedo decir en este momento, el servicio web esencialmente será una envoltura delgada sobre el BLL.

El DAL, por supuesto, tiene su propio conjunto de objetos de entidad, por ejemplo, CustomerEntity, ProductEntity, etc. Sin embargo, no quiero que la capa de presentación tenga acceso a estos objetos directamente, ya que contienen métodos DAL específicos y el ensamblaje es específico para el DAL y demás. Entonces, la idea es crear objetos de transferencia de datos (DTO). La idea es que estos serán, esencialmente, simples objetos antiguos de C # /. NET que tengan todos los campos de, por ejemplo, CustomerEntity que en realidad son la tabla de la base de datos Customer pero ninguna de las otras cosas, excepto quizás algunas propiedades IsChanged / IsDirty. Entonces, habría CustomerDTO, ProductDTO, etc. Supongo que heredarían de una clase DTO base. Creo que puedo generarlos con alguna plantilla para LLBLGen, pero todavía no estoy seguro.

Entonces, la idea es que el BLL expondrá su funcionalidad al aceptar y devolver estos objetos DTO. Creo que el servicio web se encargará de convertir estos objetos a XML para que los terceros lo usen, muchos pueden no estar usando .NET (también, algunas cosas serán secuencias de comandos ejecutables desde llamadas AJAX en la aplicación web, usando JSON).

No estoy seguro de la mejor manera de diseñar esto y exactamente cómo seguir adelante. Aquí hay algunos problemas:

1) ¿Cómo debería estar esto expuesto a los clientes (el nivel de presentación y el código del servicio web)?

Estaba pensando que habría una clase pública que tiene estos métodos, cada llamada sería una operación atómica:

InsertDTO, UpdateDTO, DeleteDTO, GetProducts, GetProductByCustomer, y así sucesivamente ...

Entonces los clientes simplemente llamarían a estos métodos y pasarían los argumentos apropiados, generalmente un DTO.

¿Es este un buen enfoque viable?

2) ¿Qué devolver de estos métodos? Obviamente, el tipo Get / Fetch de métodos devolverá DTO. Pero, ¿qué pasa con Inserts? Parte de la firma podría ser:

InsertDTO(DTO dto)

Sin embargo, al insertar lo que se debe devolver? Quiero ser notificado de errores. Sin embargo, uso claves primarias autoincrementadas para algunas tablas (Sin embargo, algunas tablas tienen claves naturales, particularmente de muchas a muchas).

Una opción que pensé fue una clase de resultado:

class Result { public Exception Error {get; set;} public DTO AffectedObject {get; set;} }

Por lo tanto, en un inserto, el DTO obtendría su propiedad get ID (como CustomerDTO.CustomerID) establecida y luego pondría en este objeto de resultado. El cliente sabrá si hay un error si Result.Error! = Null y luego sabrá el ID de la propiedad Result.AffectedObject.

¿Es este un buen enfoque? Un problema es que parece que está pasando una gran cantidad de datos de ida y vuelta que son redundantes (cuando es solo el ID). No creo que agregar una propiedad "int NewID" esté limpio porque algunas inserciones no tendrán una clave autoincrementada como esa. ¿Otro problema es que no creo que los servicios web manejen esto bien? Creo que simplemente devolverían la DTO base para AffectedObject en la clase Result, en lugar de la DTO derivada. Supongo que podría resolver esto teniendo MUCHOS tipos diferentes de objetos Result (tal vez derivados de un Resultado base y heredar la propiedad Error) pero eso no parece muy limpio.

De acuerdo, espero que esto no sea muy prolijo, pero quiero ser claro.


1: Es un enfoque bastante estándar, que se presta bien a una implementación de "repositorio" para el mejor enfoque comprobable por unidad.

2: Las excepciones (que deben declararse como "fallas" en el límite de WCF, por cierto) se activarán automáticamente. No necesita manejar eso directamente. Para los datos, hay tres enfoques comunes:

  • usar ref en el contrato (no muy bonito)
  • devolver el objeto (actualizado) - es decir, public DTO SomeOperation(DTO item);
  • devolver solo la información de identidad actualizada (clave principal / marca de tiempo / etc.)

Una cosa sobre todo esto es que no necesita un tipo diferente por operación (contraste su clase de Result , que debería duplicarse por DTO).


P1: Puede pensar en sus tipos compuestos de contrato de datos WCF como DTO para resolver este problema. De esta forma, su capa de interfaz de usuario solo tiene acceso a las propiedades DataMember de DataContract. Sus operaciones atómicas serían los métodos expuestos por su interfaz WCF.

P2: configure sus contratos de datos de respuesta para devolver un nuevo tipo personalizado con sus claves principales, etc. WCF también puede configurarse para volver a enviar las excepciones a la interfaz de usuario.