2010-11-19 42 views
-1

我使用C#編寫(假設)應用程序 - 在線商店。數據結構設計是靜態類型語言

我的產品數據庫,每個產品都有與之相關的以下信息:

  • 產品編號(必填)
  • 名稱(必須)
  • 價格(必需)
  • 評級(可選)
  • 已售數量(可選) - 這是此產品的總銷量

我有4頁顯示過濾的產品列表。頁面顯示每個產品不同的信息:

  • 第1頁:PN,名稱,價格
  • 第2頁:PN,名稱,價格,評價
  • 3D頁:PN,名稱,價格,銷售數量
  • 第4頁:PN,名稱,價格,評級,銷售數量

我的問題是,我該如何設計數據結構,以適應我幾乎沒有重複的所有網頁?

蠻力方法是爲每個頁面創建類型:

IList<Product> 
IList<ProductWithRating> 
IList<ProductWithSoldQuantity> 
IList<ProductWithRatingAndSoldQuantity> 

後3可以從Product派生但由於缺乏多重繼承ProductWithRatingAndSoldQuantity不能從兩個等級,SoldQuantity產品派生。

在動態語言中,我只需添加我需要的任何字段並且很高興。

所以,我可以通過存儲額外的信息,模擬動態語言的方法(等級,出售數量)在單獨dictonaries,如:

{ 
    IList<Product> Products; 
    IDictionary<Product, Rating> ProductRatings; 
    IDictionary<Product, SoldQuantity> ProductSoldQuantities; 
} 
// is equivalent to 
IList<ProductWithRatingAndSoldQuantities> 

構建產品結構,包括一切,然後繞過部分初始化對象是而不是我正在尋找的解決方案。

有什麼建議嗎?

回答

1

對不起沒有足夠的字符回覆評論。

您應該有一個域對象Product。它將具有不可空的名稱和ProductNumber和Price,因爲您不能擁有沒有這些東西的產品。

評級應該是可以爲空的,因爲可能有一個沒有評級的產品。無論產品是否具有評級,它仍然是一個產品。我會離開QuantitySold,因爲我不會將其作爲產品的屬性進行存儲,我會訂單和OrderLine集合,並根據這些(標準化)計算QuantitySold。但是,如果沒有其他收藏品,您可以將其作爲產品的字段存儲。如果我打算這樣做,它將是一個不可爲空的整數屬性,默認值爲零。

你只需要一個集合來過濾,這將是IEnumerable或IQueryable或兩者的一些實現,很可能你會選擇像Entity Framework這樣的東西,並且實際上有一個ObjectSet,但我會盡量讓我的設計不可知我正在使用哪種存儲方法並針對這些接口進行工作。

然後,您可以查詢您的單個集合,以確定哪些屬性在您的域模型中的產品上爲空。語法可能不完美,但沒有任何Intellisense不會完成,我是99%的VB時代的人。

var productsWithNoSales = Context.Products.Where(p=> p.QuantitySold == 0); 
var productsWithNoRating = Context.Products.Where(p=> p.Rating == nothing); 
var productsWithNoSalesOrRating = Context.Products.Where(p=> p.QuantitySold == 0).Where(p=> p.Rating == nothing); 

這幾乎是最乾淨的可能的領域模型,你爲什麼之後。

如果您有產品的專門衍生產品,它們具有額外的屬性或不同的行爲,則繼承將是。例如,我自己的系統有一個基本的Product類,以及一個EbayProduct和AmazonProduct實體,它們都從Product繼承,並且只包含與這些網站相關的額外邏輯和屬性。我的產品類有大約20個屬性 - 主要是空的,因爲當我們列出產品時,我們不一定擁有所有可用的信息。在這20箇中,我顯示在任何一個頁面上的數量大約是15個。我可能會做類似於您嘗試做的事情,因爲我會使用所描述的確切方法過濾掉尚未準備好列出的產品,即過濾我的產品集合中缺少字段。

+0

哦,當我說'ProductWithRating'時,我的意思是**類型**的名稱,它具有'Rating'作爲屬性。 'ProductWithRating' **不代表只有那些有評級的產品的集合。 – 2010-11-19 22:36:48

+0

我填充了很多或很少的屬性,因爲我可以有意義 - 通常不是所有的20在第一次嘗試。我使用EF4來完成所有的數據庫工作,因此它將所有的數據庫字段都帶回來,並且理解它們,並且實際上使用具有虛擬屬性的代理等實例化數據庫中的對象。至於你的MyRating,如果它很稀疏,我可能會將它添加爲一個新的實體/類型,與Product有0..1-1的關係(產品可以有0或1個MyRatings,MyRating只有1個產品)。 ProductWithRating路線將很快變得痛苦,不惜一切代價避免。 – RichardW1001 2010-11-19 22:56:58

+0

您是否將產品從EF傳遞到View/ViewModel? – 2010-11-19 23:00:41

1

爲什麼不能RatingSoldQuantity只能爲空?或者永遠在場,但並不總是顯示?

+0

你建議我不斷添加可添加到系統的每個新頁面的可空屬性?這會使類膨脹,會引入頁面之間的依賴關係(更改一個頁面可能需要重新編譯其他頁面)。這也構成了「部分初始化對象反模式」。 – 2010-11-19 21:28:41

1

您能儲存作爲屬性出售的評級和數量,然後存儲表明它們是否存在的布爾值?我認爲你應該在繼承時使用繼承,當然你也許應該在做作文。

+0

正是我在想什麼。 – 2010-11-19 21:07:30

+0

你建議我不斷添加(基本上)爲可添加到系統的每個新頁面的可爲空屬性?這會使類膨脹,會引入頁面之間的依賴關係(更改一個頁面可能需要重新編譯其他頁面)。這也構成了「部分初始化對象反模式」。 – 2010-11-19 21:29:15

+0

我不提倡繼承這裏,我以* brute force *解決方案爲例。 – 2010-11-19 21:29:54

0

你也許可以指定你正在使用的是什麼?你的「頁面」是什麼開始?你的數據存儲方法是什麼?

這聽起來像你混淆顯示你的數據與存儲你的數據?沒有義務僅僅因爲它存在而顯示數據。

你的對象域幾乎肯定只是有產品。數據存儲將被設置爲使屬性可以爲空,並檢查空值以獲取數據。

如果你正在使用類似的LINQ,你可以簡單地這樣做

var productsWithoutRating = Context.Products.Where(p => p.Rating == nothing); 

字典理念,繼承和組成都顯得有點怪異。存儲一個單獨的布爾值,告訴你是否存在一個屬性是混亂的,並且會是一個噩夢來維護 - 只是檢查它是否存在。

+0

您建議將添加到「產品」數據類型的任何可用於某處的信息?由於我將添加頁面,「產品」數據結構將不斷增長。每當我添加一個新頁面時 - 我將不得不重新編譯依賴於Product的每個組件。這是造成糟糕設計的原因之一。 – 2010-11-19 21:24:20

+0

另外,某些屬性可能不僅僅存在,而且不適用。例如,我添加了一個「MyRating」字段,然後生成一個用於分發的價目表。 「MyRating」在這種情況下沒有意義。 – 2010-11-19 21:26:11

+0

對於你真正想要做什麼,仍然很渾濁?什麼技術等?重新編譯一個大問題?當然你只是不經常添加字段,所以一旦設計成熟,發佈新版本就不是問題了。另一種方法是使用MVVM(模型 - 視圖 - 視圖模型)模式,並且有一個數據類 - 它將不斷髮展 - 但是爲每個定製的頁面提供一個視圖模型。 – RichardW1001 2010-11-19 21:39:11