我正在寻找一些更好的方法来在我正在使用的几个应用程序中使用List。我目前的实现看起来像这样。
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班级
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 :(得分:17)
首先,我不会从List<T>
派生出来 - 你并不是真正专注于这种行为。
我还建议您可以使Post
不可变(至少是外部的),并编写一个静态方法(或构造函数)来创建一个基于DataRow的方法:
public static Post FromDataRow(DataRow row)
同样,你可以有一个列表方法:
public static List<Post> RecentPosts()
返回它们。不可否认,在某种DAL类中可能会更好地作为实例方法,这将允许模拟等。或者,在Post:
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();
}
答案 1 :(得分:2)
编辑:John Skeet的回答可能是更好的选择。但是,如果您只想进行一些简单的更改,请继续阅读:
将数据库访问代码OpenRecentInitFromRow放入PostCollection并将其视为Post Manager类。这样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;
}
}
答案 2 :(得分:2)
您是从List&lt; T&gt;推导出来的吗?因为你想为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;
}
}
}
...
}
尽管这可能被认为是糟糕的形式(因为我们有一个可能正在进行网络调用的属性获取器),但这种迭代器方法将消除为从未枚举的Posts调用OpenRecentInitFromRow的开销。 / p>
您也不知道邮件的潜在消费者可能想要消费它们。绝对,肯定必须让每个Post都可以执行ToList()的代码,但是其他代码可能想要使用LINQ查询,该查询在找到正确的Post之后使枚举短路。
答案 3 :(得分:2)
我正在寻找一些更好的方法来使用List
这似乎是一个奇怪的要求。 “列表”类型是一种手段,很少是结束。考虑到这一点,实现真正结束的一种更好的方法是使用IEnumerable而不是List,因为该List强制您将整个集合保留在内存中,而IEnumerable一次只需要一个对象。诀窍在于,您必须在处理流中连接所有,从数据层一直到演示,然后使用它。
我在下面的链接中有一个很好的例子,说明如何以非常干净的方式执行此操作:
Fastest method for SQL Server inserts, updates, selects
根据您现有的数据层代码,您可以浏览(长)帖子的前半部分 - 主要的一点是您使用迭代器块将SqlDataReader转换为IEnumerable<IDataRecord>
。一旦掌握了这一点,其余部分就会非常简单。
答案 4 :(得分: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>
}
}