2010-05-25 73 views
9

我正在尋找實施一些更好的方式來使用列表在我正在處理的幾個應用程序。我目前的實施看起來像這樣。什麼是更好,更乾淨的方式使用列表<T>

MyPage.aspx.cs

protected void Page_Load(object sender, EventArgs e) 
{ 
    BLL.PostCollection oPost = new BLL.PostCollection(); 
    oPost.OpenRecent(); 
    rptPosts.DataSource = oArt; 
    rptPosts.DataBind(); 
} 

BLL類(S)

public class Post 
{ 
    public int PostId { get; set; } 
    public string PostTitle { get; set; } 
    public string PostContent { get; set; } 
    public string PostCreatedDate { get; set; } 

    public void OpenRecentInitFromRow(DataRow row) 
    { 
     this.PostId = (int) row["id"]; 
     this.PostTitle = (string) row["title"]; 
     this.PostContent = (string) row["content"]; 
     this.PostCreatedDate = (DateTime) row["createddate"]; 
    } 
} 
public class PostCollection : List<Post> 
{ 
    public void OpenRecent() 
    { 
     DataSet ds = DbProvider.Instance().Post_ListRecent(); 
     foreach (DataRow row in ds.Tables[0].Rows) 
     { 
      Post oPost = new Post(); 
      oPost.OpenRecentInitFromRow(row); 
      Add(oPost); 
     } 
    } 
} 

現在,雖然這工作都很好,如果有任何的方式來提高我只是想知道它只是使它更清潔,不得不使用兩個不同的類來做我認爲可能發生在一個類或使用接口的事情。

+0

有什麼辦法讓你的數據庫層返回除了表以外的其他東西(例如使用數據讀取器填充你的對象列表)嗎? – Paddy 2010-05-25 13:36:17

+2

這可能是個人偏好,但我也會從您的頁面代碼中丟棄匈牙利符號。 – Paddy 2010-05-25 13:37:01

+0

@Paddy - 我正在努力!我只用它來幫助我記住某些事情,比如中繼器。但是它們都在慢慢地被淘汰出代碼。 – 2010-05-25 14:32:35

回答

17

一兩件事,我不會從List<T>派生 - 你是不是真的專業的行爲。

我還建議你可以做Post不可變的(至少在外部),並寫一個靜態方法(或構造函數)的基礎上DataRow中創建一個:

public static Post FromDataRow(DataRow row) 

同樣可以擁有列表方法:

public static List<Post> RecentPosts() 

返回它們。誠然,這可能是作爲一個實例方法在某種DAL類的,這將使嘲諷等另外,在後更好:

public static List<Post> ListFromDataSet(DataSet ds) 

現在,作爲使用List<T>本身 - 您使用。 NET 3.5?如果是這樣,你可以相當整潔使用LINQ使這個:

public static List<Post> ListFromDataSet(DataSet ds) 
{ 
    return ds.Tables[0].AsEnumerable() 
         .Select(row => Post.FromDataRow(row)) 
         .ToList(); 
} 
+7

+1爲「不從派生列表」 - 很少,如果有的話,你想這樣做。**喜歡組合繼承!**(有效的Java,項目16 ) – 2010-05-25 13:49:58

+0

在這種情況下甚至不需要編寫組合 – 2010-05-25 13:54:36

+2

此外,具體不是來自列表。通常繼承收藏通常會更好,因爲它給你添加,刪除等方法,你可以覆蓋 – RichK 2010-05-25 13:54:55

2

編輯:John Skeet的回答可能是一個更好的選擇。但是,如果您只想進行一些簡單的更改,請繼續閱讀:

將數據庫訪問代碼OpenRecentInitFromRow放入PostCollection中,並將其視爲Post管理器類。這樣Post類是一個普通的舊數據傳輸對象。

public class Post 
{ 
    public int PostId { get; set; } 
    public string PostTitle { get; set; } 
    public string PostContent { get; set; } 
    public string PostCreatedDate { get; set; } 
} 

public class PostCollection : List<Post> 
{ 
    public void OpenRecent() 
    { 
     DataSet ds = DbProvider.Instance().Post_ListRecent(); 
     foreach (DataRow row in ds.Tables[0].Rows) 
     { 
      Add(LoadPostFromRow(row)); 
     } 
    } 

    private Post LoadPostFromRow(DataRow row) 
    { 
     Post post = new Post(); 
     post.PostId = (int) row["id"]; 
     post.PostTitle = (string) row["title"]; 
     post.PostContent = (string) row["content"]; 
     post.PostCreatedDate = (DateTime) row["createddate"]; 
     return post; 
    } 
} 
+0

我喜歡這個想法。但最後,我試圖消除這兩個階級在一個可以訣竅的地方。此外,我從來不喜歡我使用的PostCollection類,我認爲它看起來很醜陋,更不用說我確信這種方法會有性能開銷....也許,它運行得很好,我有很多的內存和時鐘週期來備用!! – 2010-05-25 15:02:28

0

你可以這樣做:

protected void Page_Load(object sender, EventArgs e) 
{ 
    BLL.PostCollection oPost = new BLL.PostCollection(); 
    rptPosts.DataSource = Post.OpenRecent(); 
    rptPosts.DataBind(); 
} 
public class Post 
{ 
    public int PostId { get; set; } 
    public string PostTitle { get; set; } 
    public string PostContent { get; set; } 
    public string PostCreatedDate { get; set; } 

    public void OpenRecentInitFromRow(DataRow row) 
    { 
     this.PostId = (int) row["id"]; 
     this.PostTitle = (string) row["title"]; 
     this.PostContent = (string) row["content"]; 
     this.PostCreatedDate = (DateTime) row["createddate"]; 
    } 

    public static List<Post> OpenRecent() 
    { 
     DataSet ds = DbProvider.Instance().Post_ListRecent(); 
     foreach (DataRow row in ds.Tables[0].Rows) 
     { 
      Post oPost = new Post(); 
      oPost.OpenRecentInitFromRow(row); 
      Add(oPost); //Not sure what this is doing 
     } 
     //need to return a List<Post> 
    } 
} 
2

你從名單<獲得牛逼>因爲要提供其他消費者PostCollection的能力添加和刪​​除項目?我不會猜測,而且你實際上只是想要一種方法來公開你可以綁定的集合。如果是的話,你可以考慮一個迭代器,也許是:

class BLL { 
    ... 

    public IEnumerable<Post> RecentPosts { 
     get { 
      DataSet ds = DbProvider.Instance().Post_ListRecent(); 
      foreach (DataRow row in ds.Tables[0].Rows) 
      { 
       Post oPost = new Post(); 
       oPost.OpenRecentInitFromRow(row); 
       yield return oPost; 
      } 
     } 
    }  

    ... 
} 

儘管事實上,這可能被認爲是拙劣的形式(在我們有一個屬性的getter可能被製作網絡電話),這個迭代方法將做遠離調用OpenRecentInitFromRow用於從未列舉的帖子的開銷。

您也成爲您的帖子的潛在消費者如何消費它們的不可知論者。絕對肯定必須讓每個Post都可以執行ToList()的代碼,但其他代碼可能希望使用LINQ查詢,在找到正確的Post後將枚舉短路。

+0

使用'yield return xxx'處理另一個'IEnumerable <>'後,我真的很喜歡它是如何工作的。在這個時候,我仍然需要與所有的帖子合作來設置一些緩存和分頁,但我會在不久的將來重新訪問其他一些數據集。 – 2010-07-20 12:48:34

2

我期待實現一些更好的方法來使用List

這似乎是一個奇怪的要求。 「列表」類型是一種手段,很少是結束。考慮到這一點,實現真正目標的一種更好的方法是使用IEnumerable而不是List,因爲List會強制您將整個集合保存在內存中,而IEnumerable一次只需要一個對象。訣竅就是您必須將的所有內容連接到您的處理流中,從數據層一直到演示文稿,才能使用它。

我在下面關於如何做到這一點的一個非常乾淨的方式鏈接一個很好的例子:
Fastest method for SQL Server inserts, updates, selects

根據現有數據層代碼,您可以撇去太多的上半年(長)文章 - 主要觀點是您使用迭代器塊來將SqlDataReader變成IEnumerable<IDataRecord>。一旦你有了它,其餘的過程都非常簡單。

+0

感謝您的提示,我將會看到這個以及剛剛開始的另一個應用程序,並且我希望第一次儘可能地做到儘可能好! – 2010-05-26 17:55:11

相關問題