2012-06-30 42 views
2

我知道這是相當基本的東西,但請隨身攜帶。這裏很熱(目前35攝氏度),所以我的大腦可能處於融化階段。C#數據庫訪問,Dapper,SQL和POCOs - 編程設計

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

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)一個新的屬性添加到類產品

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模式

第一種方法似乎是錯誤的我(儘管我一直USI長時間),因爲我試圖建立一個分層的Web應用程序。我不確定硬編碼這是一個好方法。

第二種方法更好,但更糟糕的是它不容易重複使用。如果我有多個地方我正在做同樣的事情和一些變化,...也許它會工作,如果我指定一些靜態常量保存路徑...

第三種可能性似乎相當複雜的可維護性方面。我的課程數量可能會翻一番。如果我現在有30班,它會突然變爲60:/

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

編輯:

好吧,也許我本來應該更具體的...從戈文德KamalaPrakash馬爾維亞的解決方案是偉大的,但不能每次都使用。我需要一種方法來解決任何類型的屬性,甚至是更復雜的屬性 - 例如某些相冊的照片數量。查詢照片的數量和相冊是一個好主意,但將它分配給什麼?使用Decorator模式創建裝飾類?

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

回答

1

我通常通過使該實體對象,因爲它是和創建一個額外的數據容器解決這個問題,這將要麼保持對相應實體的引用,要麼從實體對象本身實現相應的屬性。在後一種情況下,我使用映射庫(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); 
       }; 
    } 
} 
+0

謝謝你的回答!謹慎展示一個例子,使用你的方法會是什麼樣子?聽起來有點像Decorator模式與Factory模式的結合。 :-) – walther

+0

我添加了一個簡單的例子。它使用一個工廠,但這也可能只是另一個類中的工廠方法。它沒有實現Decorator模式,但可以根據需要擴展。我儘量保持簡單。 – EagleBeak

+0

謝謝。我會等待別人是否提出了不同的解決方案,如果不是,我可能會選擇你的答案,因爲它似乎更適合我的需求,而不是Govinds的回答。 – walther

4

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

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"); 
+0

完美的答案.. –

+0

公共靜態字符串的ImageUrl(字符串imageName,串directoryUrl = 「defaulturl」) –

+0

是的,這看起來很有希望。我也在想類似的事情,只是忘記提到它。但是,如果所需的額外屬性稍微複雜一點呢?就像我想顯示的專輯中的照片數量和專輯列表一樣。我不會把它放到我的sql模式中,也不能用這種方法來完成。 – walther