使用自定義實體類和集合代替DataSet

使用自定義實體類和集合代替DataSet

作者:  文章來源:http://www.51item.net   時間:2007-4-27 15:13:50   閱讀次數:97

DataSet的問題:
1、缺少抽象,開發人員必須瞭解其基礎架構;
2、弱類型,返回的是System.Object,必須進行類型轉換Convert.ToInt32等之後才能使用,降低了效率,增加了出錯的可能性;
3、不是面向對象的,無法充分利用OO的技術。
使用DataSet,它的缺點將在複雜系統中成倍的擴大。

自定義實體類的挑戰:
要求更多的代碼。我們不是簡單地獲取數據並自動填充 DataSet,而是獲取數據並手動將數據映射到自定義實體(必須先創建好)。由於這個工作是重複的,我們可以使用代碼生成工具或者ORM映射。

自定義實體類的代碼示例:
public class User {
#region "Fields and Properties"
private int userId;
private string userName;
private string password;
public int UserId {
get { return userId; }
set { userId = value; }
  }
public string UserName {
get { return userName; }
set { userName = value; }
}
public string Password {
get { return password; }
set { password = value; }
}
#endregion
#region "Constructors"
public User() {}
public User(int id, string name, string password) {
this.UserId = id;
this.UserName = name;
this.Password = password;
}
#endregion
}

自定義實體類的優點:
1、可以讓我們利用繼承和封裝等OO技術;
2、可以添加自定義行爲;
3、屬於強類型,可以獲得代碼自動完成功能(IntelliSense);
4、屬於強類型,不太需要容易出錯的強制類型轉換。

對象和關係的映射:
public User GetUser(int userId) {
SqlConnection connection = new SqlConnection(CONNECTION_STRING);
SqlCommand command = new SqlCommand("GetUserById", connection);
command.Parameters.Add("@UserId", SqlDbType.Int).Value = userId;
SqlDataReader dr = null;
try{
connection.Open();
dr = command.ExecuteReader(CommandBehavior.SingleRow);
if (dr.Read()){
User user = new User();
user.UserId = Convert.ToInt32(dr["UserId"]);
user.UserName = Convert.ToString(dr["UserName"]);
user.Password = Convert.ToString(dr["Password"]);
return user;           
  }
return null;
}finally{
if (dr != null && !dr.IsClosed){
dr.Close();
  }
connection.Dispose();
command.Dispose();
}
}

以上代碼還保留着DataSet弱類型需要轉換這樣的缺點,所以應該進一步改進,即將映射的轉換過程提取到一個函數中,使這段代碼能夠重複使用——

public User PopulateUser(IDataRecord dr) {
User user = new User();
user.UserId = Convert.ToInt32(dr["UserId"]);
//檢查 NULL 的示例
if (dr["UserName"] != DBNull.Value){
user.UserName = Convert.ToString(dr["UserName"]);  
}
user.Password = Convert.ToString(dr["Password"]);
return user;
}

需要說明1:我們不對映射函數使用 SqlDataReader,而是使用 IDataRecord。這是所有 DataReader 實現的接口。使用 IDataRecord 使我們的映射過程獨立於供應商。也就是說,我們可以使用上一個函數從 Access 數據庫中映射 User,即使它使用 OleDbDataReader 也可以。如果您將這個特定的方法與 Provider Model Design Pattern(鏈接 1鏈接 2)結合使用,您的代碼就可以輕鬆地用於不同的數據庫提供程序。
需要說明2:數據訪問是否該和自定義實體類放在一起?爲了擴展和維護的方便,通常應該將數據訪問層和業務層明確分離。

自定義集合:
簡單的解決方案是使用Arraylist,但它的問題和DataSet相關,即也是弱類型,無法添加自定義行爲。幸虧 Microsoft .NET Framework 提供了一個專門爲了此目的而繼承的類:CollectionBaseCollectionBase 的工作原理是,將所有類型的對象都存儲在專有 Arraylist 中,但是通過只接受特定類型(例如 User 對象)的方法來提供對這些專有集合的訪問。代碼示例——

public class UserCollection :CollectionBase {
public User this[int index] {
get {return (User)List[index];}
set {List[index] = value;}
}
public int Add(User value) {
return (List.Add(value));
}
public int IndexOf(User value) {
return (List.IndexOf(value));
}
public void Insert(int index, User value) {
List.Insert(index, value);
}
public void Remove(User value) {
List.Remove(value);
}
public bool Contains(User value) {
return (List.Contains(value));
}
}

映射到自定義集合:
將我們的關係數據映射到自定義集合的過程與我們對自定義實體執行的過程非常相似。我們不再創建一個實體並將其返回,而是將該實體添加到集合中並循環到下一個:

public UserCollection GetAllUsers() {
SqlConnection connection = new SqlConnection(CONNECTION_STRING);
SqlCommand command =new SqlCommand("GetAllUsers", connection);
SqlDataReader dr = null;
try{
connection.Open();
dr = command.ExecuteReader(CommandBehavior.SingleResult);
UserCollection users = new UserCollection();
while (dr.Read()){
users.Add(PopulateUser(dr));
  }
return users;
}finally{
if (dr != null && !dr.IsClosed){
dr.Close();
  }
connection.Dispose();
command.Dispose();
}
}

添加自定義行爲:
示例一
public User FindUserById(int userId) {
foreach (User user in List) {
if (user.UserId == userId){
return user;
  }
}
return null;
}
示例二
public UserCollection FindMatchingUsers(string search) {
if (search == null){
throw new ArgumentNullException("search cannot be null");
}
UserCollection matchingUsers = new UserCollection();
foreach (User user in List) {
string userName = user.UserName;
if (userName != null && userName.StartsWith(search)){
matchingUsers.Add(user);
  }
}
return matchingUsers;
}

綁定自定義集合:  [轉自:51item.net]  
自定義集合綁定到web控件和DataSet一樣很簡單(這是因爲 CollectionBase 實現了用於綁定的 Ilist)。自定義集合可以作爲任何控件的 DataSource,而 DataBinder.Eval 只能像您使用 DataSet 那樣使用——

UserCollection users = DAL.GetAllUsers();
repeater.DataSource = users;
repeater.DataBind();

<!-- HTML -->
<asp:Repeater onItemDataBound="r_IDB" ID="repeater" Runat="server">
<ItemTemplate>
<asp:Label ID="userName" Runat="server">
<%# DataBinder.Eval(Container.DataItem, "UserName") %><br />
</asp:Label>
</ItemTemplate>
</asp:Repeater>

高級內容:
1、併發
2、性能
3、排序與篩選
4、代碼生成
5、ORM映射
6、泛型
7、可以爲空的類型
8、迭代程序

【強烈推薦參考:《DataSet與自定義實體類以及集合的比較》】
DataSets vs. Collections by Dino Esposito對比分析了DataSet, Typed DataSet和Custom Entities and Collections(定製業務實體和集合)作爲multi-tier之間的數據傳遞,並闡述各自的適用情況(When to Use Which)。

文章建議:在小型項目中,考慮到預算、截至時間等因素,可以使用DataSet快速開發。如果項目時間長、投入多,業務邏輯複雜,則使用自定義實體類以及集合,對於維護、擴展、靈活、代碼的優雅、單元測試等,都能帶來益處。前期的投入是值得的。

文章建議閱讀:For more information on these topics, take a look at the following blogs: Scott Hanselmans at Returning DataSets from WebServices is the Spawn of Satan and Represents All That Is Truly Evil in the World, Jelle Druyts at DataSets Are Not Evil, Andrew Conrads at Nix the DataSet??????, and ObjectSharp at DataSet FAQ.

各項比較:

  DataSet Typed DataSet Custom Entities
Built-in support for concurrency Yes Yes To be added
Data Relationship Yes Yes No
Serialization Inefficient in .NET Framework 1.x Same as DataSet, but can be improved To be added
NULL values No Yes To be added
Schema abstraction Yes Yes Yes
Strong typing No Yes Yes
Support for hierarchical data Yes, but through a relational API Yes, but through a relational API Yes
Free-form data No No Yes
Custom behavior No To be added Yes
Ease of development Yes Yes No, but can be improved through custom wizards and code generation
.NET data binding Yes Yes To be added; requires the implementation of several additional interfaces
Interfacing with Web services Costly, unless knowledge of the object is assumed on the client Schema information is more precise and can be handled by the client Yes
XML integration Yes Yes To be added
Expression language Yes Yes To be added
Data aggregation Yes Yes To be added
如果採用Custom Entities,建議瞭解如下常用的Enterprise Design Patterns:
Design Patterns for Building a DAL
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章