說明:個人感覺在Java領域大型開發都離不了ORM的身影,所謂的SSH就是 Spring+Struts+Hibernate,除了在學習基礎知識的時候被告知可以使用JDBC操 作數據庫之外,大量的書籍中都是講述使用Hibernate這個ORM工具來操作數據。 在.NET中操作數據庫的方式有多種,除了最直接的方式就是使用ADO.NET之外, 還可以使用NHibernate這個Hibernate在.NET中的實現ORM,如果你對第三方的 ORM持懷疑態度,你還可以使用來自微軟的實現、根正苗紅的Linq或者 EntityFramework。
大部分從早期就開始使用.NET開發的程序員可能對ADO.NET有種迷戀,使用 ADO.NET可以充分將我們早期的SQL知識發揮得淋漓盡致,並且出於對性能的考慮 ,有些人對.NET中的ORM還保持一種觀望態度,包括我自己也是這種態度。不過 即使在實際開發中不用,並不代表我們不能去了解和比較這些技術,任何事物的 出現和消亡總有其原因的,我們可以了解它們的優點和長處。所以本人抽出了幾 個周末的時間分別用ADO.NET、NHibernate、Linq和 EntityFramework來實現對 數據庫單表數據的創建、讀取、更新和刪除操作,也就是所謂的CRUD (C:Create/R:Read /U:Update/D:Delete)。
通過實現相同功能的比較,大家自己判斷那種方式更適合自己。需要說明的 是,如果在VS2008中使用 EntityFramework就需要安裝VS2008SP1。
在開始演示之前先准備好數據,在本系列中所使用的數據庫是SQL Server2005,創建和初始化數據庫數據的代碼如下:
/****** 對象: Table [dbo].[UserInfo] 腳本日期: 03/08/2010 12:20:11 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[UserInfo]') AND type in (N'U'))
BEGIN
CREATE TABLE [dbo].[UserInfo](
[UserID] [int] IDENTITY(1,1) NOT NULL,
[UserName] [varchar](20) COLLATE Chinese_PRC_CI_AS NOT NULL,
[RealName] [nvarchar](8) COLLATE Chinese_PRC_CI_AS NOT NULL,
[Age] [tinyint] NOT NULL,
[Sex] [bit] NOT NULL,
[Mobile] [char](11) COLLATE Chinese_PRC_CI_AS NULL,
[Phone] [char](11) COLLATE Chinese_PRC_CI_AS NULL,
[Email] [varchar](50) COLLATE Chinese_PRC_CI_AS NOT NULL,
CONSTRAINT [PK_UserInfo] PRIMARY KEY CLUSTERED
(
[UserID] ASC
)WITH (IGNORE_DUP_KEY = OFF)
)
END
GO
IF NOT EXISTS (SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[dbo].[UserInfo]') AND name = N'IX_UserName')
CREATE UNIQUE NONCLUSTERED INDEX [IX_UserName] ON [dbo]. [UserInfo]
(
[UserName] ASC
)WITH (IGNORE_DUP_KEY = ON)
GO
下面開始演示如何使用ADO.NET實現CRUD功能。
一、配置
創建一個控制台或者類庫項目,並且添加一個app.config配置文件,在此文 件中添加數據庫配置信息,如下:
<connectionStrings>
<add name="Conn" connectionString="Data Source=zhou;Initial Catalog=AspNetStudy;User ID=sa;Password=jerry" />
</connectionStrings>
二、創建實體類
using System;
using System.Collections.Generic;
using System.Text;
namespace ADODoNETDemo
{
public class UserInfo
{
/// <summary>
/// 用戶編號
/// </summary>
public int UserId { get; set; }
/// <summary>
/// 用戶名
/// </summary>
public string UserName { get; set; }
/// <summary>
/// 真實姓名
/// </summary>
public string RealName { get; set; }
/// <summary>
/// 年齡
/// </summary>
public byte Age { get; set; }
/// <summary>
/// 性別
/// </summary>
public bool Sex { get; set; }
/// <summary>
/// 電子郵件
/// </summary>
public string Email { get; set; }
/// <summary>
/// 手機號
/// </summary>
public string Mobile { get; set; }
/// <summary>
/// 電話
/// </summary>
public string Phone { get; set; }
}
}
三、創建數據庫訪問通用類
說明:下面的這個數據庫通用類適用於訪問數據庫中任意表,不管是基於文 本方式SQL、參數化SQL語句或者存儲過程都可以。
很郁悶受篇幅限制,這裡將代碼放在附件裡。
四、創建CRUD類
對數據庫實現增刪改查功能的類的代碼如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SqlClient;
using System.Data;
namespace ADODoNETDemo
{
/// <summary>
/// 用ADO.NET實現CRUD功能
/// </summary>
public class ADODotNetCRUD
{
/// <summary>
/// 統計用戶總數
/// </summary>
/// <returns></returns>
public int Count()
{
string sql = "select count(1) from UserInfo";
SqlDbHelper db = new SqlDbHelper();
return int.Parse (db.ExecuteScalar(sql).ToString());
}
/// <summary>
/// 創建用戶
/// </summary>
/// <param name="info">用戶 實體</param>
/// <returns></returns>
public bool Create(UserInfo info)
{
string sql = "insert UserInfo(UserName,RealName,Age,Sex,Mobile,Email,Phone) values(@UserName,@RealName,@Age,@Sex,@Mobile,@Email,@Phone)";
SqlParameter[] paramters = new SqlParameter[]{
new SqlParameter("@UserName",info.UserName),
new SqlParameter("@RealName",info.RealName),
new SqlParameter("@Age",info.Age),
new SqlParameter("@Sex",info.Sex),
new SqlParameter("@Mobile",info.Mobile),
new SqlParameter("@Email",info.Email),
new SqlParameter("@Phone",info.Phone),
};
SqlDbHelper db = new SqlDbHelper();
return db.ExecuteNonQuery(sql, CommandType.Text, paramters) > 0;
}
/// <summary>
/// 讀取用戶信息
/// </summary>
/// <param name="userId">用 戶編號</param>
/// <returns></returns>
public UserInfo Read(int userId)
{
string sql = "select * from UserInfo Where UserId="+userId;
SqlDbHelper db = new SqlDbHelper();
DataTable data = db.ExecuteDataTable(sql);
if (data.Rows.Count > 0)
{
DataRow row = data.Rows[0];
UserInfo info = new UserInfo()
{
UserId=int.Parse(row["UserId"].ToString()),
UserName=row["UserName"].ToString(),
Age=byte.Parse(row["Age"].ToString()),
Email=row["Email"].ToString(),
Mobile=row["Mobile"].ToString(),
Phone=row["Phone"].ToString(),
RealName=row["RealName"].ToString(),
Sex=bool.Parse(row["Sex"].ToString())
};
return info;
}
else
{
return null;
}
}
/// <summary>
/// 更新用戶信息
/// </summary>
/// <param name="info">用戶 實體</param>
/// <returns></returns>
public bool Update(UserInfo info)
{
string sql = "update UserInfo set UserName=@UserName,RealName=@RealName,Age=@Age,Sex=@Sex,Mobile=@Mobile ,Email=@Email,Phone=@Phone where UserID=@UserID";
SqlParameter[] paramters = new SqlParameter[]{
new SqlParameter("@UserName",info.UserName),
new SqlParameter("@RealName",info.RealName),
new SqlParameter("@Age",info.Age),
new SqlParameter("@Sex",info.Sex),
new SqlParameter("@Mobile",info.Mobile),
new SqlParameter("@Email",info.Email),
new SqlParameter("@Phone",info.Phone),
new SqlParameter("@UserID",info.UserId),
};
SqlDbHelper db = new SqlDbHelper();
return db.ExecuteNonQuery(sql, CommandType.Text, paramters) > 0;
}
/// <summary>
/// 刪除用戶
/// </summary>
/// <param name="userId">用 戶編號</param>
/// <returns></returns>
public bool Delete(int userId)
{
string sql = "delete from UserInfo where UserId=" + userId;
SqlDbHelper db = new SqlDbHelper();
return db.ExecuteNonQuery(sql) > 0;
}
/// <summary>
/// 獲取用戶表中編號最大的用戶
/// </summary>
/// <returns></returns>
public int GetMaxUserId()
{
string sql = "select max(userId) from UserInfo";
SqlDbHelper db = new SqlDbHelper();
return int.Parse (db.ExecuteScalar(sql).ToString());
}
}
}
五、NUnit單元測試代碼
在進行單元測試時沒有使用VS自帶的單元測試工具,仍是我平常用慣了的 NUnit,下面是代碼:
很遺憾,受篇幅限制,這裡代碼也以附件形式提供。
六、點評
在使用ADO.NET操作數據庫時個人覺得有如下優點,可以隨心所欲地使用熟知 的SQL語句甚至是存儲過程,在使用統計、分組功能時感覺尤其強烈,當然前提 是你的SQL基礎要相當好,此外它是其它幾種ORM的基礎,其它幾種ORM都是在底 層使用ADO.NET實現與數據庫的交互的,所以在效率上來說它也要高一些。它的 缺點是需要自己寫操作數據的語句並且需要自己編寫數據庫記錄到實體的映射轉 換代碼,一旦表的結構發生變動,就需要修改實體類和映射轉換代碼。
出處http://zhoufoxcn.blog.51cto.com/792419/283952