C#數據庫訪問,Dapper,SQL和POCO - 編程設計

asp.net dapper design-patterns oop sql

我知道這是相當基本的東西,但請和我一起出去。這裡很熱(目前35C),所以我的大腦可能處於融化階段。

長話短說,假設我們在C#中用SQL表示這樣的表:

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

現在我們將查詢數據庫並檢索對象,假設使用如下值:

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

一切都很正常。我現在正在思考的是:如果我想要展示產品,我需要一些未在數據庫中查詢的其他信息,例如圖像的確切文件路徑,我們所擁有的只是

apple.jpg

,但我們需要類似的東西

〜/圖像/ apple.jpg


所以,我想到了3種可能性:

1.)向Product類添加一個新屬性

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

2.)在執行表示邏輯期間指定完整的URL,假設:

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

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

3.)使用Decorator模式

第一種方法對我來說似乎不對(即使我已經使用了很長時間),因為我正在嘗試使用分層Web應用程序。我不確定硬編碼這是一個很好的方法。

第二種方法更好,但在某種意義上它更難以重複使用。如果我有多個地方,我正在做同樣的事情和一些變化,...如果我指定一些保持路徑的靜態常量,它可能會工作...

就可維護性而言,第三種可能性似乎相當複雜。我的課程數量可能要翻倍。如果我現在有30個課程,它會突然變成60個:/

這樣做的最佳/推薦方式是什麼?如果我向未包含在db模式中的POCO添加屬性,我將無法使用Dapper.Contrib或Rainbow和類似的庫,因為即使“選擇”工作正常,我也不能“插入”或“刪除”。我必須為每個命令硬編碼sql字符串,這些命令在一段時間後變得非常乏味,當你一直在做同樣的事情時。

編輯:

好吧,也許我應該更具體......來自Govind KamalaPrakash Malviya的解決方案很棒,但不能每次都使用。我需要一種方法來解決任何類型的屬性,即使是那些更複雜的屬性 - 例如某些專輯的照片數量。查詢照片的數量以及相冊是個好主意,但是將它分配給什麼?使用Decorator模式創建一個裝飾類?

你如何解決這種架構問題?

一般承認的答案

我通常通過將實體對象保持原樣並創建一個額外的數據容器來解決這個問題,該容器將保存對相應實體的引用或從實體對象本身實現相應的屬性。在後一種情況下,我使用映射庫( AutoMapper )將數據從實體複製到增強容器。

填充額外屬性的邏輯通常在於工廠(或工廠方法)。這取決於您,您希望將其置於您的架構中。在當前項目中,我們將它們包含在客戶端的數據訪問外觀中,因為我們不希望使用太多DTO來混淆數據訪問層。這當然意味著,數據訪問層仍然需要支持檢索額外的屬性。在你的情況下像int GetNumberOfPhotosForAlbum(Album album)這樣的操作。

我們發現這些好處超過了數據訪問層不斷增長的合同的風險,當然這可能需要支持許多不同的調用,如上面的示例,而不僅僅是EnhancedAlbum GetEnhancedAlbumWithAllKindsOfExtraProperties(long albumId) 。在某些情況下,這可能也會成為性能問題,因為服務調用頻率增加的開銷。最後,您需要決定什麼是最適合您的項目。

我喜歡這種方法,因為我的實體( Album )保持不變,我在持久性,客戶端邏輯和映射之間保持明確的關注點分離。

例:

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

熱門答案

我認為你應該在表示層操作它,因為只有表示層的圖像路徑。所以使用第三個,但使用實用方法很容易

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

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

    } 
}

並輕鬆使用它

PathUtility.ImageUrl("apple.jpg");


許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因
許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因