what practices pattern framework best c# orm castle-activerecord dto-mapping
vinculado

practices - web api c# entity framework



Sugerencias sobre cómo asignar objetos de dominio(ORM) a objetos de transferencia de datos(DTO) (5)

Mis disculpas por no poner los detalles aquí, pero un enfoque básico de OO sería convertir al DTO en miembro de la clase ActiveRecord y hacer que ActiveRecord delegue los accessors y mutators en el DTO. Puede usar herramientas de generación de código o refactorización para crear las clases de DTO con bastante rapidez desde las clases de AcitveRecord.

El sistema actual en el que estoy trabajando utiliza Castle Activerecord para proporcionar ORM (mapeo relacional de objetos) entre los objetos de dominio y la base de datos. ¡Todo está bien y la mayoría de las veces funciona bien!

El problema se produce con el soporte de Castle Activerecords para la ejecución asincrónica, bueno, más específicamente el SessionScope que administra la sesión a la que pertenecen los objetos. En resumen, ¡cosas malas suceden!

Por lo tanto, estamos buscando una forma de convertir fácilmente (piense automágicamente) de los objetos de Dominio (que saben que un DB existe y se preocupa) al objeto DTO (que no saben nada sobre el DB y no les importan las sesiones, atributos de mapeo ni nada) ORM).

¿Alguien tiene sugerencias para hacer esto? Para empezar, estoy buscando un mapeo de objetos básico de uno a uno. El objeto de dominio Persona se asignará para decir PersonDTO . No quiero hacerlo manualmente porque es un desperdicio.

Obviamente, viene a la mente la reflexión, pero espero que con algunos de los mejores conocimientos de TI que flotan en este sitio se sugiera "más fresco" .

Oh, estoy trabajando en C #, los objetos ORM como se dijo antes de un mapeado con Castle ActiveRecord.

Código de ejemplo:

Por petición de @ ajmastrean, he vinculado un ejemplo de que me he burlado (mal) de todos. El ejemplo tiene un formulario de captura , un controlador de formulario de captura, objetos de dominio , un depósito de registro activo y un auxiliar asíncrono . Es un poco grande (3MB) porque incluí los dll ActiveRecored necesarios para ejecutarlo. Tendrá que crear una base de datos llamada ActiveRecordAsync en su equipo local o simplemente cambiar el archivo .config.

Detalles básicos del ejemplo:

El formulario de captura

La forma de captura tiene una referencia al controlador

private CompanyCaptureController MyController { get; set; }

En la inicialización de la forma, llama a MyController.Load () private void InitForm () {MyController = new CompanyCaptureController (this); MyController.Load (); } Esto volverá a un método llamado LoadComplete ()

public void LoadCompleted (Company loadCompany) { _context.Post(delegate { CurrentItem = loadCompany; bindingSource.DataSource = CurrentItem; bindingSource.ResetCurrentItem(); //TOTO: This line will thow the exception since the session scope used to fetch loadCompany is now gone. grdEmployees.DataSource = loadCompany.Employees; }, null); } }

aquí es donde ocurre lo "malo" , ya que estamos usando la lista infantil de la Compañía que está configurada como carga diferida.

El controlador

El controlador tiene un método Load que se llamó desde el formulario, luego llama al Asyc helper para llamar asincrónicamente al método LoadCompany y luego vuelve al método LoadComplete del formulario Capture.

public void Load () { new AsyncListLoad<Company>().BeginLoad(LoadCompany, Form.LoadCompleted); }

El método LoadCompany () simplemente utiliza el Repositorio para encontrar una empresa conocida.

public Company LoadCompany() { return ActiveRecordRepository<Company>.Find(Setup.company.Identifier); }

El resto del ejemplo es bastante genérico, tiene dos clases de dominio que heredan de una clase base, un archivo de configuración para insertar algunos datos y el repositorio para proporcionar las capacidades de ActiveRecordMediator .


Resolví un problema muy similar al que copié los datos de muchos contratos de servicios web más antiguos en contratos de datos de WCF. Creé una cantidad de métodos que tenían firmas como esta:

public static T ChangeType<S, T>(this S source) where T : class, new()

La primera vez que este método (o cualquiera de las otras sobrecargas) se ejecuta para dos tipos, examina las propiedades de cada tipo y decide cuáles existen en ambos en función del nombre y el tipo. Toma esta ''intersección de miembros'' y utiliza la clase DynamicMethod para emil la IL para copiar el tipo de fuente al tipo de destino, luego almacena en caché el delegado resultante en un diccionario estático threadsafe.

Una vez que se crea el delegado, es obscenamente rápido y he proporcionado otras sobrecargas para pasar a un delegado y copiar las propiedades que no coinciden con los criterios de intersección:

public static T ChangeType<S, T>(this S source, Action<S, T> additionalOperations) where T : class, new()

... así que podrías hacer esto para tu ejemplo Person to PersonDTO:

Person p = new Person( /* set whatever */); PersonDTO = p.ChangeType<Person, PersonDTO>();

Y cualquier propiedad tanto en Person como PersonDTO (una vez más, que tienen el mismo nombre y tipo) sería copiada por un método emitido en tiempo de ejecución y cualquier llamada subsiguiente no tendría que ser emitida, pero reutilizaría el mismo código emitido para esos tipos en ese orden (es decir, copiar PersonDTO a Persona también incurriría en un golpe para emitir el código).

Es demasiado código para publicar, pero si estás interesado haré el esfuerzo de subir una muestra a SkyDrive y publicar el enlace aquí.

Ricardo


En realidad, ahora estoy totalmente confuso. Porque está diciendo: "Por lo tanto, estamos buscando una forma de convertir fácilmente (piense automágicamente) de los objetos de Dominio (que saben que existe un DB y cuidar) al objeto DTO (que no saben nada del DB y no se preocupan por las sesiones , atributos de mapeo o todo lo que es ORM). "

  1. ¿Los objetos de dominio conocen y se preocupan por DB? ¿No es el objetivo de los objetos de dominio el contener SOLAMENTE la lógica de negocios y ser totalmente inconscientes de DB y ORM? .... ¿TIENE que tener estos objetos? Solo necesitas REPARARlos si contienen todo eso ... es por eso que estoy un poco confundido acerca de cómo los DTO entran en escena

  2. ¿Podría proporcionar más detalles sobre los problemas que enfrenta con la carga diferida?



use ValueInjecter , con él puede asignar cualquier cosa a cualquier cosa, por ejemplo

  • objeto <-> objeto
  • object <-> Form / WebForm
  • DataReader -> objeto

y tiene características geniales como: aplanar y no aplanar

la descarga contiene muchas muestras