天天看點

ADO.NET與ORM的比較(3)Linq to SQL實作CRUD

說明:個人感覺在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 ,如需轉載請自行聯系原作