說明:個人感覺在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。
語言內建查詢 (LINQ) 是 Visual Studio 2008 中的一組功能,可為 C# 和 Visual Basic 語言文法提供強大的查詢功能。LINQ 引入了标準的、易于學習的查詢和更新資料模式,可以對其技術進行擴充以支援幾乎任何類型的資料存儲。Visual Studio 2008 包含 LINQ 提供程式的程式集,這些程式集支援将 LINQ 與 .NET Framework 集合、SQL Server 資料庫、ADO.NET 資料集和 XML 文檔一起使用。
在本篇講述利用Linq實作對資料庫的CRUD功能,也就是Linq to SQL,需要說明的是Linq to SQL隻支援SQL Server資料庫,Linq to SQL隻是Linq的一部分功能。
用Linq to SQL來操作資料庫确實比使用NHibernate在操作上要友善得多,通過下面的操作讀者也會體會得到,畢竟這個是微軟官方的東東,微微支援的力度自然要大些。
一、準備
首先,向項目中添加Linq To SQL的類,如下圖所示:
在名稱一欄中填寫較友好的名字之後,然後項目中就會增加一個字尾為dbml的檔案,輕按兩下這個檔案就會進入設計視圖,如下圖所示:
在伺服器資源管理中找到相應的資料庫連接配接,依次點開之後就可以将資料庫中的表拖到dbml設計器上。如果讀者界面上沒有伺服器資料總管可以使用CTRL+ALT+S組合鍵将其調出來。如果沒有資料庫連接配接,可以按照下面的步驟進行,在伺服器資料總管中的“資料連接配接”——“添加連接配接”,出現如下界面:
在上面的界面中依次填寫好資料庫、使用者名和密碼及要連接配接的庫名之後,點選确定,這樣在伺服器資料總管中就增加了一個資料庫連接配接,展開之後如下圖所示:
拖拽一個表到dbml上就會自動生成這個表的實體類,如下圖所示:
也許有人會思考這個類的定義在哪裡,可以告訴你的是這個類的定義在這個dbml檔案對應的cs檔案中(dbml檔案名.designer.cs這種形式),如下圖所示:
有些這些之後我們就可以動手編碼實作對資料庫進行CRUD操作了。
二、編碼
由于在dbml檔案中已經存在了DataContext和UserInfo表對應的UserInfo實體類,是以我們僅僅需要編寫對資料庫操作的類就可以了。編寫的代碼如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SqlClient;
using System.Data.Linq;
using System.Configuration;
namespace LinqDemo
{
/// <summary>
/// 說明:這個類是為了示範.NET中的Linq to SQL的用法
/// 作者:周公(周金橋)
/// 日期:2010-03-01
/// </summary>
public class LinqCRUD
{
/// <summary>
/// 統計使用者總數
/// </summary>
/// <returns></returns>
public int Count()
{
方法一#region 方法一
//使用SqlConnection來執行個體化DataContext對象
SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["LinqDemo.Properties.Settings.AspNetStudyConnectionString"].ConnectionString);
DataContext context = new DataContext(connection);
IEnumerable<int> collection = context.ExecuteQuery<int>("select count(1) from UserInfo");
int count = collection.ElementAt<int>(0);
return count;
#endregion
方法二#region 方法二
//UserInfoDataClassesDataContext context = new UserInfoDataClassesDataContext();
////return context.UserInfo.Count<UserInfo>(item => item.Age > 23);//帶條件統計
//return context.UserInfo.Count<UserInfo>();
}
/// 建立使用者
/// <param name="info">使用者實體</param>
public void Create(UserInfo info)
UserInfoDataClassesDataContext context = new UserInfoDataClassesDataContext();
context.UserInfo.InsertOnSubmit(info);
context.SubmitChanges();
/// 讀取使用者資訊
/// <param name="userId">使用者編号</param>
public UserInfo Read(int userId)
context.Log = Console.Out;
var query = from item in context.UserInfo
where item.UserID == userId
select item;
return query.First<UserInfo>();
/// 更新使用者資訊
public void Update(UserInfo info)
UserInfo ui = context.UserInfo.First<UserInfo>(item => item.UserID == info.UserID);
ui.Age = info.Age;
ui.Email = info.Email;
ui.Mobile = info.Mobile;
ui.Phone = info.Phone;
ui.RealName = info.RealName;
ui.Sex = info.Sex;
ui.UserName = info.UserName;
/// 删除使用者
public void Delete(int userId)
//context.ExecuteCommand("delete from UserInfo where UserId=" + userId);
UserInfo ui = context.UserInfo.First<UserInfo>(item => item.UserID == userId);
context.UserInfo.DeleteOnSubmit(ui);
/// <param name="userId">使用者實體</param>
public void Delete(UserInfo info)
var userList = from Users
in context.UserInfo
where Users.UserID == info.UserID
select Users;
foreach (var user in userList)
{
context.UserInfo.DeleteOnSubmit(user);
}
//context.UserInfo.DeleteOnSubmit(userList.First<UserInfo>());
//注意下面的寫法是錯誤的
// context.UserInfo.DeleteOnSubmit(info);
/// 擷取使用者表中編号最大的使用者
public int GetMaxUserId()
int userId=context.UserInfo.Max<UserInfo>(item => item.UserID);
return userId;
}
}
說明,在上面的代碼中每個方法的第一句都是執行個體化一個叫UserInfoDataClassesDataContext的類,這個類我們并沒有編寫,但是奇怪的是上面的代碼居然能編譯通過,這是為什麼呢?原來秘密還是在那個dbml檔案中,這個類在dbml的設計檔案中的定義如下:
[System.Data.Linq.Mapping.DatabaseAttribute(Name="AspNetStudy")]
public partial class UserInfoDataClassesDataContext : System.Data.Linq.DataContext
//.....省略其它代碼
可以看出UserInfoDataClassesDataContext是繼承DataContext的,這個DataContext在MSDN中的定義為:
DataContext 是通過資料庫連接配接映射的所有實體的源。它會跟蹤您對所有檢索到的實體所做的更改,并且保留一個“辨別緩存”,該緩存確定使用同一對象執行個體表示多次檢索到的實體。
也就是我們用DataContext來與資料庫進行互動,DataContext會根據上下文環境來決定如何與資料庫互動,正因為如此,是以我們用Linq to SQL的代碼才如此簡單!
三、單元測試代碼
using NUnit.Framework;
using LinqDemo;
namespace NUnitTest
[TestFixture]
public class LinqTest
private LinqCRUD instance = null;
[SetUp]
public void Initialize()
instance = new LinqCRUD();
[Test]
public void Count()
Assert.Greater(instance.Count(), 0);
public void Create()
UserInfo info = new UserInfo()
Age = 12,
Email = "[email protected]",
Mobile = "13812345678",
Phone = "01012345678",
RealName = "測試" + DateTime.Now.Millisecond.ToString(),
Sex = true,
UserName = "zhoufoxcn" + DateTime.Now.Millisecond.ToString()
};
instance.Create(info);
public void Read()
UserInfo info = instance.Read(1);
Assert.NotNull(info);
public void Update()
info.RealName = "測試" + DateTime.Now.Millisecond.ToString();
instance.Update(info);
public void DeleteByID()
int userId = instance.GetMaxUserId();
instance.Delete(userId);
public void Delete()
UserInfo info = instance.Read(userId);
//Console.WriteLine("MaxUserId=" + userId);
instance.Delete(info);
上面的代碼在NUnit2.5.3中測試通過。
四、總結
NHibernate與ADO.NET相比開發更簡單,應對資料庫的變化更靈活,而Linq to SQL比NHibernate更友善應對資料庫變化,開發效率也高,使用Linq to SQL後我們僅需要編寫一個類就足夠了,比較遺憾的是Linq to SQL隻支援SQL Server,是以很多人都在使用Entity Framework這個ORM架構了。
本文轉自周金橋51CTO部落格,原文連結:http://blog.51cto.com/zhoufoxcn/293966 ,如需轉載請自行聯系原作