Acceso a bases de datos C #, Dapper, SQL y POCOs - diseño de programación

asp.net dapper design-patterns oop sql

Pregunta

Sé que esto es bastante básico, pero por favor, desnudo conmigo. Hace bastante calor aquí (35C en este momento), por lo que mi cerebro probablemente esté en su fase de fusión.

Para resumir, digamos que tenemos una tabla en SQL representada en C # como esta:

public class Product
{
   public int ID { get; set; }
   public string Name { get; set; }
   public string Picture { get; set; } // filename of the picture, e.g. apple.jpg
   public int CategoryID { get; set; }
}

Ahora consultaríamos la base de datos y recuperaríamos el objeto, digamos con valores como este:

ID = 1
Name = Yellow apple
Picture = apple.jpg
CategoryID = 25

Todo perfectamente normal. Lo que estoy meditando en este momento es esto: si quiero mostrar un producto, necesito información adicional que no fue consultada desde la base de datos, como la ruta exacta de archivo a la imagen, todo lo que tenemos es

apple.jpg

, pero necesitamos tal vez algo así como

~ / images / apple.jpg


Entonces, estaba pensando en 3 posibilidades:

1.) agregar una nueva propiedad a la clase Producto

public string PictureUrl
{
    get
    {
        return "~/images/apple.jpg";
    }
}

2.) especifique la URL completa durante la ejecución de la lógica de presentación, digamos:

public void ShowProductDetails()
{
    Product p = ProductRepo.GetProduct(id);

    txtName.Text = p.Name;
    imgPicture.ImageUrl = "~/images/" + p.Picture;
}

3.) use el patrón Decorator

El primer enfoque me parece incorrecto (aunque lo he usado durante bastante tiempo), porque estoy tratando de tener una aplicación web en capas. No estoy seguro de que esta sea una buena forma de hacerlo.

El segundo enfoque es mejor, pero peor en el sentido de que no se puede reutilizar fácilmente. Si tengo varios lugares en los que estoy haciendo lo mismo y algo cambia, ... Tal vez funcionaría si especificara algunas constantes estáticas que contengan las rutas ...

La tercera posibilidad parece bastante complicada en términos de mantenibilidad. El número de mis clases probablemente tendría que duplicarse. Si ahora tengo 30 clases, de repente se convertiría en 60: /

¿Cuál es la mejor / manera recomendada de hacer cosas como esta? Si agrego propiedades a mis POCO que no están incluidas en el esquema db, no puedo usar Dapper.Contrib o Rainbow y bibliotecas similares, porque aunque "selecciona" funciona bien, no puedo "insertar" ni " borrar". Tengo que codificar las cadenas sql para cada comando que se vuelve realmente tedioso después de un tiempo, cuando estás haciendo todo el tiempo las mismas cosas.

EDITAR:

OK, tal vez debería haber sido más específico ... La solución de Govind KamalaPrakash Malviya es genial, pero no se puede usar todo el tiempo. Necesito una forma de resolver esto para cualquier tipo de propiedades, incluso aquellas más complejas, por ejemplo, la cantidad de fotos de algún álbum. Es una buena idea consultar el recuento de fotos junto con los álbumes, pero asignarlo a qué? ¿Crea una clase decorada usando un patrón Decorator?

¿Cómo resuelves este tipo de problemas de arquitectura?

Respuesta aceptada

Normalmente resuelvo esto dejando el objeto de la entidad tal como está y creando un contenedor de datos adicional, que o bien mantendrá una referencia a la entidad correspondiente o implementará las propiedades correspondientes desde el objeto de la entidad en sí. En este último caso, utilizo una biblioteca de mapeo ( AutoMapper ) para copiar datos de una entidad a un contenedor mejorado.

La lógica para llenar las propiedades adicionales normalmente se encuentra en una fábrica (o método de fábrica). Depende de usted, donde desea colocar esto en su arquitectura. En un proyecto actual los incluimos en nuestra fachada de acceso a datos en el lado del cliente, porque no queremos saturar la capa de acceso a datos con demasiados DTO. Esto, por supuesto, significa que la capa de acceso a datos aún necesita admitir la recuperación de las propiedades adicionales. En su caso, una operación como int GetNumberOfPhotosForAlbum(Album album) .

Descubrimos que los beneficios superan el riesgo de un contrato cada vez mayor de la capa de acceso a datos, que por supuesto podría necesitar muchas llamadas diferentes como el ejemplo anterior en lugar de solo EnhancedAlbum GetEnhancedAlbumWithAllKindsOfExtraProperties(long albumId) . Esto también podría convertirse en un problema de rendimiento en algunos escenarios, debido a la sobrecarga de una mayor frecuencia de llamadas de servicio. Al final, debe decidir qué es lo mejor para su proyecto.

Me gusta este enfoque, porque mis entidades ( Album ) permanecen intactas y mantengo una clara separación de preocupaciones entre la persistencia, la lógica del cliente y el mapeo.

Ejemplo:

class Album
{
    string Name { get; set; }
}

class EnhancedAlbum
{
    Album Album { get; set; }
    int NumberOfPhotos { get; set; }
}

class EnhancedAlbumFactory
{
    private MyDataService _dataService;

    //include some means of constructing or (better) injecting the data service

    EnhancedAlbum GetEnhancedAlbum(Album album)
    {
        return new EnhancedAlbum
               {
                   Album = Album,
                   NumberOfPhotos = _dataService.GetNumberOfPhotosForAlbum(album);
               };
    }
}

Respuesta popular

Creo que debería manipularlo en la capa de presentación porque la ruta de la imagen solo para la capa de presentación. así que use el tercero pero hágale fácil usar el método de utilidad

public class PathUtility
{
    public static string ImageUrl(string imageName)
    {

          if(string.IsNullOrEmpty(imageName))
          {
               throw new Exception("Image name not valid!!");
          } 
          else
          {
               return "YourImageDirectroyUrl" + imageName;
          }

    } 
}

y usarlo fácilmente

PathUtility.ImageUrl("apple.jpg");


Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow