Accès à la base de données C #, Dapper, SQL et POCO - conception de la programmation

asp.net dapper design-patterns oop sql

Question

Je sais que c'est un truc assez basique, mais s'il te plaît, nu avec moi. Il fait très chaud ici (35C en ce moment), donc mon cerveau est probablement en phase de fusion.

En bref, disons que nous avons une table en SQL représentée en C # comme ceci:

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

Maintenant, nous interrogerions la base de données et récupérerions l'objet, disons avec des valeurs comme celles-ci:

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

Tout est parfaitement normal. La chose que je médite en ce moment est la suivante: si je veux montrer un produit, j'ai besoin d'informations supplémentaires qui n'ont pas été interrogées à partir de la base de données, comme le chemin d'accès exact à l'image.

apple.jpg

, mais nous avons peut-être besoin de quelque chose comme

~ / images / apple.jpg


Donc, je pensais à 3 possibilités:

1.) ajouter une nouvelle propriété à la classe Product

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

2.) spécifiez l'URL complète lors de l'exécution de la logique de présentation, disons:

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

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

3.) utiliser un motif de décorateur

La première approche me semble erronée (même si je l'utilise depuis assez longtemps), car j'essaie d'avoir une application Web en couches. Je ne suis pas sûr que coder en dur c'est une bonne façon de faire.

La deuxième approche est meilleure, mais pire dans le sens où elle ne peut pas être facilement réutilisée. Si j'ai plusieurs endroits où je fais la même chose et que quelque chose change, ... Peut-être que cela fonctionnerait si je spécifiais des constantes statiques contenant les chemins ...

La troisième possibilité semble assez compliquée en termes de maintenabilité. Le nombre de mes cours devrait probablement doubler. Si j'ai 30 classes maintenant, ça deviendrait soudainement 60: /

Quelle est la meilleure façon de faire les choses? Si j'ajoute des propriétés à mes POCO qui ne sont pas incluses dans le schéma de la base de données, je ne peux pas utiliser Dapper.Contrib ou Rainbow et des bibliothèques similaires, car même si "select" fonctionne correctement, je ne peux "ni" ni "insérer" effacer". Je dois coder en dur les chaînes SQL pour chaque commande qui devient vraiment fastidieuse après un certain temps, quand vous faites tout le temps les mêmes choses.

MODIFIER:

OK, peut-être aurais-je dû être plus précis ... La solution de Govind KamalaPrakash Malviya est géniale, mais ne peut pas être utilisée à chaque fois. J'ai besoin d'un moyen de résoudre ce problème pour tout type de propriétés, même les plus complexes - par exemple, le nombre de photos d'un album. C'est une bonne idée d'interroger le nombre de photos avec les albums, mais l'affecter à quoi? Créez une classe décorée en utilisant un motif Décorateur?

Comment résous-tu ce genre de problèmes d'architecture?

Réponse acceptée

Je résous normalement ce problème en laissant l'objet entité tel quel et en créant un conteneur de données supplémentaire, qui contiendra soit une référence à l'entité correspondante, soit implémentera les propriétés correspondantes de l'objet entité lui-même. Dans ce dernier cas, j'utilise une bibliothèque de mappage ( AutoMapper ) pour copier des données d'une entité dans un conteneur amélioré.

La logique de remplissage des propriétés supplémentaires réside normalement dans une usine (ou une méthode d'usine). C'est à vous de voir où vous voulez placer cela dans votre architecture. Dans un projet en cours, nous les incluons dans notre façade d'accès aux données côté client, car nous ne voulons pas encombrer la couche d'accès aux données avec trop de DTO. Cela signifie bien sûr que la couche d'accès aux données doit encore prendre en charge la récupération des propriétés supplémentaires. Dans votre cas, une opération comme int GetNumberOfPhotosForAlbum(Album album) .

Nous avons constaté que les avantages l' emportent sur le risque d'un contrat sans cesse croissant de la couche d'accès aux données, ce qui bien sûr peut - être besoin de soutenir de nombreux appels différents comme l'exemple ci - dessus au lieu de seulement EnhancedAlbum GetEnhancedAlbumWithAllKindsOfExtraProperties(long albumId) . Cela peut également devenir un problème de performances dans certains scénarios, en raison de la surcharge liée à l'augmentation de la fréquence des appels de service. En fin de compte, vous devez décider de ce qui convient le mieux à votre projet.

J'aime cette approche, car mes entités ( Album ) restent intactes et je garde une nette séparation des préoccupations entre persistance, logique client et mappage.

Exemple:

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

Réponse populaire

Je pense que vous devriez le manipuler dans la couche de présentation car le chemin de l'image pour la couche de présentation uniquement. donc utilisez le troisième mais rendez-le facile en utilisant la méthode utilitaire

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

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

    } 
}

et l'utiliser facilement

PathUtility.ImageUrl("apple.jpg");



Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi