C # -Datenbankzugriff, Dapper, SQL und POCOs - Programmierentwurf

asp.net dapper design-patterns oop sql

Frage

Ich weiß, das ist ziemlich einfaches Zeug, aber bitte, bare mit mir. Es ist ziemlich heiß hier (momentan 35 Grad), also ist mein Gehirn wahrscheinlich in seiner Schmelzphase.

Lange Rede, kurzer Sinn, nehmen wir an, wir haben eine Tabelle in SQL, die in C # wie folgt dargestellt wird:

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

Jetzt würden wir die Datenbank abfragen und das Objekt abrufen, sagen wir mit Werten wie dieser:

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

Alles vollkommen normal. Die Sache, über die ich im Moment nachdenke, ist folgende: Wenn ich ein Produkt zeigen möchte, brauche ich einige zusätzliche Informationen, die nicht von der Datenbank abgefragt wurden, wie der genaue Dateipfad zum Bild, alles was wir haben ist

apple.jpg

, aber wir brauchen vielleicht so etwas wie

~ / Bilder / Apfel.jpg


Also habe ich an 3 Möglichkeiten gedacht:

1.) füge der Klasse Product eine neue Eigenschaft hinzu

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

2.) Geben Sie die vollständige URL während der Ausführung der Präsentationslogik an, sagen wir:

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

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

3.) Dekorationsmuster verwenden

Der erste Ansatz scheint mir falsch zu sein (obwohl ich ihn schon ziemlich lange benutzt habe), weil ich versuche, eine mehrschichtige Webanwendung zu erstellen. Ich bin mir nicht sicher, ob es hart ist, das zu programmieren. Das ist ein guter Weg.

Der zweite Ansatz ist besser, aber schlechter in dem Sinne, dass er nicht einfach wiederverwendet werden kann. Wenn ich mehrere Orte habe, an denen ich dasselbe mache und sich etwas ändert, ... Vielleicht würde es funktionieren, wenn ich einige statische Konstanten festlege, die die Pfade halten ...

Die dritte Möglichkeit erscheint im Hinblick auf die Wartbarkeit ziemlich kompliziert. Die Anzahl meiner Klassen würde sich wahrscheinlich verdoppeln. Wenn ich jetzt 30 Klassen habe, würde es plötzlich 60 werden: /

Was ist die beste / empfohlene Art, solche Dinge zu tun? Wenn ich Eigenschaften zu meinen POCOs hinzufüge, die nicht im db-Schema enthalten sind, kann ich Dapper.Contrib oder Rainbow und ähnliche Bibliotheken nicht verwenden, denn obwohl "selects" gut funktioniert, kann ich weder "einfügen" noch "" löschen". Ich muss die SQL-Strings für jeden Befehl hart codieren, was nach einiger Zeit wirklich langweilig wird, wenn man die ganze Zeit die gleichen Sachen macht.

BEARBEITEN:

OK, vielleicht hätte ich genauer sein sollen ... Die Lösung von Govind KamalaPrakash Malviya ist großartig, aber kann nicht jedes Mal benutzt werden. Ich brauche einen Weg, um das für jede Art von Eigenschaften zu lösen, auch für die komplexeren - zum Beispiel die Anzahl der Fotos eines Albums. Es ist eine gute Idee, die Anzahl der Fotos zusammen mit den Alben abzufragen, aber zu was? Erstellen Sie eine dekorierte Klasse mit einem Decorator-Muster?

Wie lösen Sie diese Art von Architekturproblemen?

Akzeptierte Antwort

Normalerweise löse ich dies, indem ich das Entitätsobjekt belassen und einen zusätzlichen Datencontainer erstelle, der entweder einen Verweis auf die entsprechende Entität enthält oder die entsprechenden Eigenschaften aus dem Entitätsobjekt selbst implementiert. Im letzteren Fall verwende ich eine Mapping-Bibliothek ( AutoMapper ), um Daten von einer Entität in einen erweiterten Container zu kopieren.

Die Logik zum Füllen der zusätzlichen Eigenschaften liegt normalerweise in einer Fabrik (oder Fabrikmethode). Es liegt an Ihnen, wo Sie dies in Ihrer Architektur platzieren möchten. In einem aktuellen Projekt nehmen wir sie auf der Clientseite in unsere Datenzugriffsfassade auf, weil wir die Datenzugriffsebene nicht mit zu vielen DTOs überladen wollen. Dies bedeutet natürlich, dass die Datenzugriffsebene das Abrufen der zusätzlichen Eigenschaften weiterhin unterstützen muss. In Ihrem Fall ein Vorgang wie int GetNumberOfPhotosForAlbum(Album album) .

Wir haben festgestellt, dass die Vorteile das Risiko eines ständig wachsenden Vertrags der Datenzugriffsebene überwiegen, der natürlich viele verschiedene Aufrufe wie das obige Beispiel unterstützen muss und nicht nur EnhancedAlbum GetEnhancedAlbumWithAllKindsOfExtraProperties(long albumId) . Dies kann in einigen Szenarios auch zu einem Leistungsproblem führen, da die Häufigkeit von Serviceaufrufen höher ist. Am Ende müssen Sie entscheiden, was für Ihr Projekt am besten ist.

Ich mag diesen Ansatz, weil meine Entitäten ( Album ) unberührt bleiben und ich eine klare Trennung der Belange zwischen Persistenz, Client-Logik und Mapping behalte.

Beispiel:

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

Beliebte Antwort

Ich denke, Sie sollten es in Präsentationsschicht manipulieren, da der Bildpfad nur für die Präsentationsebene ist. also benutze den dritten, aber mach es einfach mit der Utility-Methode

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

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

    } 
}

und benutze es einfach

PathUtility.ImageUrl("apple.jpg");


Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum
Lizenziert unter: CC-BY-SA with attribution
Nicht verbunden mit Stack Overflow
Ist diese KB legal? Ja, lerne warum