日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關咨詢
選擇下列產品馬上在線溝通
服務時間:8:30-17:00
你可能遇到了下面的問題
關閉右側工具欄

新聞中心

這里有您想知道的互聯(lián)網營銷解決方案
數據訪問層DAL實現(xiàn)過程

這里為了演示上簡單,假設:后臺數據庫(暫為SqlServer只有用戶表User與部門表Department),各表字段相應精簡:

創(chuàng)新互聯(lián)公司專注于中大型企業(yè)的網站建設、成都網站建設和網站改版、網站營銷服務,追求商業(yè)策劃與數據分析、創(chuàng)意藝術與技術開發(fā)的融合,累計客戶上千多家,服務滿意度達97%。幫助廣大客戶順利對接上互聯(lián)網浪潮,準確優(yōu)選出符合自己需要的互聯(lián)網運用,我們將一直專注高端網站設計和互聯(lián)網程序開發(fā),在前進的路上,與客戶一起成長!

User(用戶表)
Id 主鍵
Name 姓名
DeptId 部門編號
其余字段省略......

  

Department(部門表)
Id 主鍵
Name 名稱
Desc 部門描述
其余字段省略......

  后臺數據庫:testdb的情況

建立相關的存儲過程:

一般我個人也喜歡ORM轉換成實體對象(見截圖)

(注意:這里增加了DeptTitle屬性<部門名稱>)

  現(xiàn)在就是訪問數據庫SqlServer類型,封裝到SqlserverProvider中。如果將來訪問Access數據庫,對應訪問封裝到AccessProvider中。

  (Provider這里表示數據訪問提供程序)

  SqlUserProvier專門實現(xiàn)對SqlServer的表User的操作,AccessUserProvider專門實現(xiàn)對Access的表User的操作,很顯然,操作功能都相同(增刪改查),因而對不同子類的相同部分抽象出來,形成父類(UserProvider)。

開始著手具體子類實現(xiàn):SqlUserProvider:UserProvider

  (上圖數據庫連接串錯誤:單詞integrated才是正確的,***面調試錯誤后改正。)

  我們發(fā)現(xiàn)重載的GetUsers方法,大量代碼重復,進行方法重構(重復代碼重構為方法GetUsersFromReader)!

  繼續(xù)具體實現(xiàn)父類的抽象方法:GetUserById,發(fā)現(xiàn)該方法的部分代碼與先前的GetUsersFromReader方法中的部分代碼又重復了!

  發(fā)現(xiàn)上圖紅色部分重復(該圖GetUserById方法忘記傳遞存儲過程所需的參數了),再接著方法重構,提煉重復的代碼,避免以后改動的多次修改。

  接著編寫該類后續(xù)的方法(增/刪/改):(可以打開VS開發(fā)環(huán)境中的<服務器資源管理器>,連接上對應的數據庫后,看存儲過程的參數,以免編碼遺忘傳參)

接著也來看看 類:AccessUserProvider,見下圖

  上圖GetUsers方法中的查詢語句沒有聯(lián)合查詢,后續(xù)會改動。(這里僅僅示范,其似Access是可以類似建立查詢表<后臺調用類似存儲過程方式>)

  我們發(fā)現(xiàn)UserProvider的兩個子類的方法GetUserFromReader和GetUsersFromReader有重復代碼(僅僅是方法的參數不同) [想辦法抽象出來,放在父類中]

  而方法的參數雖然是SqlDataReader與OleDbDataReader,但是查看定義,看到它們有自己的父類:DbDataReader。

  public class SqlDataReader :DbDataReader, IDataReader, IDisposable, IDataRecord

  public sealed class OleDbDataReader :DbDataReader

  改寫父類:UserProvider

父類的方法加上修飾符protected,是為了確保只有子類能夠訪問。

  子類便可以直接調用父類的方法了(GetUserFromReader和GetUsersFromReader方法),見截圖:

類似的完善SqlDepartmentProvider類和AccessDepartmentProvider類的代碼

 ?。ǜ割悾篋epartmentProvider提供保護方法GetDeparmentFromReader和GetDepartmentsFromReader)

  每個具體的子類Provider都重復了屬性:ConnString,所以決定建一個父類:DataAccess來存放該屬性(UserProvider與DepartProvider都繼承自它),實際上DataAccess還可以包含其它的屬性和共用方法。

 
 
 
 
  1. namespace抽象工廠模式.DAL
  2. {
  3. publicabstractclassDataAccess
  4. {
  5. privatestring_connString ="";
  6. publicstringConnString
  7. { get{ return_connString; } }
  8. }
  9. }

   public abstract class UserProvider:DataAccess

  public abstract class DepartmentProvider:DataAccess

  通常:數據庫連接串的內容都是存儲在對應的配置文件中,而不硬編碼。

  桌面應用程序—[app.config],web應用程序---[web.config],這里以app.config示例,數據庫連接串先按照SqlServer數據庫訪問的。

 
 
 
 
  1. connectionString="SERVER=.sqlexpress;DATABASE=testdb;INTEGRATED SECURITY=true"/>

  一定要手動引用:System.configuration,然后通過ConfigurationManager類來訪問連接串。

  可以想象,根據數據庫的類型不同,實際底層操控的數據提供程序為Sql__Provider或是Access__Provider。

  但對于用戶調用者(業(yè)務邏輯層)只需要操控Provider就可以了。

  假設我所在城市有兩個行政分區(qū)(東一區(qū)和西二區(qū)),有一家“真不錯”總店[經營快餐系列的]在這兩個區(qū)都有連鎖店,對外統(tǒng)一電話:1111777。

  (設一個總機號碼當然方便了,總不至于將來開了10家分店,對外公布10個電話號碼,誰能記住啊?)

  比如說:我現(xiàn)在餓了,想吃這家提供的“經濟型快餐(一素<炒萵苣>一湯<豆腐湯>)”,我只要打電話111177,那邊只需要了解我的地址就可以了。(可以想象:知道了我的地址<就能明白所在行政區(qū),然后公司總店去指派所在區(qū)的分店來服務>),對于客戶我而言:如何指派哪家分店來服務,以及經濟型快餐如何制作的,我都不會關心的。我只關心:要好吃,然后要快點(畢竟,餓太久會受不了的。)

  回到我們的程序:

  UserProvider好比一個物品蔬菜<萵苣>,DepartmentProvider好比湯菜<豆腐>。Access文件夾[經濟型],SqlServer文件夾[商務型] (你會問一個題外問題:有葷菜嗎?我的回答是:盡量別吃,如今都是激素喂出來的<現(xiàn)在人們消耗太快了,以前自然方式半年才能長大的動物,如今1個月人工方式就用激素喂成了>。吃多了,身體容易得病)。

  只有一個問題:既然BLL(相對于DAL就是客戶調用者)只認(UserProvider/DepartmentProvider),又是如何調用實際其作用的子類呢?

  這就需要用到設計模式中的<簡單工廠模式> (具體選擇哪個子類實際上用父類來完成<根據客戶配置需求>)

當然這里的配置文件:數據庫連接串和providerType需要匹配好。

  父類:UserProvider我們提供靜態(tài)的Instance,來決定實際的子類(SqlUserProvider或者AccessUserProvider,根據配置文件的ProviderType的value來定)

  如果將來出現(xiàn)了OracleUserProvider/DB2UserProvider/MySqlUserProvider/XmlUserProvider,這個藍色框框仍然需要增加case分支。這就不好了,需要再編碼(修改),好的設計方式應該是對擴展開放,對修改封閉。而且這里羅列出了所有的具體子類Provider,其實只需要一個子類Provider,但是其他的子類Provider也被迫出現(xiàn)在一起<大雜燴>(其實子類之間出現(xiàn)了耦合) 所以這種方式不可取,需要解決。

  這里用反射的方式來解決這個問題。

  首先約束:ProviderType的賦值需要規(guī)范,只能從(Sql/Access/DB2/MySql/Xml)選擇一個呢??梢园l(fā)現(xiàn):實際的子類名:ProviderType的值+“UserProvider”。

 
 
 
 
  1. staticpublicUserProvider Instance
  2. {
  3. get
  4. {
  5. if(_instance == null)
  6. {
  7. stringproviderTypeName=ConfigurationManager.AppSettings["ProviderType"]
  8. +"UserProvider";
  9. _instance =
  10. Activator.CreateInstance(Type.GetType(providerTypeName)) asUserProvider;
  11. }
  12. return_instance;
  13. }
  14. }

  如果:你的DAL是單獨用程序集方式建立的項目(類庫),請使用Assembly.Load等方式,這里由于是以文件夾方式組織的(DAL文件夾)<用Activator.CreateInstance可以OK.>

  以后客戶端(BLL)調用的時候:比如刪除用戶表的記錄,就可以如下調用了:

  UserProvider.Instance.DeleteUser(id)了。//這里BLL已經不知道是由哪個子類(如SqlUserProvider)來實際工作的。

  進行一下測試,看是否運行正常!

  發(fā)現(xiàn)錯誤:一:數據庫連接串需要修改:

二:文件夾SqlServer改成Sql。以前的命名空間對應改動下:

  namespace抽象工廠模式.DAL.Provider.Sql

  {

  publicclassSqlDepartmentProvider:DepartmentProvider

  ………………………………………….

  namespace抽象工廠模式.DAL.Provider.Sql

  {

  publicclassSqlUserProvider:UserProvider

  ………………………………………………………….

  三:Type.GetType(需要完整的限定名)

測試通過:但發(fā)現(xiàn)沒有DeptTitle數據,查找錯誤發(fā)現(xiàn)

 
 
 
 
  1.   publicUser(intid, stringname, intdeptId, stringdeptTitle)
  2.   {
  3.   this.Id = id;
  4.   this.Name = name;
  5.   this.DeptId = deptId;
  6.   this.DeptTitle = deptTitle; //DeptTitle;
  7.   }

附上:AccessUserProvider的代碼如下:

AccessUserProvider代碼

 

 
 
 
 
  1. usingSystem;
  2. usingSystem.Collections.Generic;
  3. usingSystem.Text;
  4. usingSystem.Data;
  5. usingSystem.Data.OleDb;
  6. using抽象工廠模式.DAL;
  7. using抽象工廠模式.DAL.Entity;
  8. namespace抽象工廠模式.DAL.Provider.Access
  9. {
  10. publicclassAccessUserProvider:UserProvider
  11. {
  12. publicoverrideList GetUsers()
  13. {
  14. using(OleDbConnection conn = newOleDbConnection(ConnString))
  15. {
  16. vardbcmd = conn.CreateCommand();
  17. dbcmd.CommandText = "GetUsers";
  18. dbcmd.CommandType = CommandType.StoredProcedure;
  19. conn.Open();
  20. returnGetUsersFromReader(dbcmd.ExecuteReader());
  21. }
  22. }
  23. publicoverrideList GetUsers(intdeptId)
  24. {
  25. using(OleDbConnection conn = newOleDbConnection(ConnString))
  26. {
  27. vardbcmd = conn.CreateCommand();
  28. dbcmd.CommandText = "GetUsersByDepartmentId";
  29. dbcmd.CommandType = CommandType.StoredProcedure;
  30. dbcmd.Parameters.Add("@DeptId", OleDbType.Integer).Value = deptId;
  31. conn.Open();
  32. returnGetUsersFromReader(dbcmd.ExecuteReader());
  33. }
  34. }
  35. publicoverrideUser GetUserById(intid)
  36. {
  37. using(OleDbConnection conn = newOleDbConnection(ConnString))
  38. {
  39. vardbcmd = conn.CreateCommand();
  40. dbcmd.CommandText = "GetUserById";
  41. dbcmd.CommandType = CommandType.StoredProcedure;
  42. dbcmd.Parameters.Add("@Id", OleDbType.Integer).Value =id ;
  43. conn.Open();
  44. returnGetUserFromReader(dbcmd.ExecuteReader());
  45. }
  46. }
  47. publicoverrideboolDeleteUser(intid)
  48. {
  49. using(OleDbConnection conn = newOleDbConnection(ConnString))
  50. {
  51. OleDbCommand cmd = newOleDbCommand(
  52. "delete from [user] where Id="+ id, conn);
  53. conn.Open();
  54. returncmd.ExecuteNonQuery() == 1;
  55. }
  56. }
  57. publicoverrideintInsertUser(User user)
  58. {
  59. using(OleDbConnection conn = newOleDbConnection(ConnString))
  60. {
  61. OleDbCommand cmd = newOleDbCommand(
  62. @"insert into [user](name,deptId) values(@id,@name);68select max(id) from [user] as newid",conn);
  63. cmd.Parameters.Add("@id", OleDbType.Integer).Value = user.Id;
  64. cmd.Parameters.Add("@name", OleDbType.VarChar).Value = user.Name;
  65. conn.Open();
  66. return(int)cmd.ExecuteScalar();
  67. }
  68. }
  69. publicoverrideboolUpdateUser(User user)
  70. {
  71. using(OleDbConnection conn = newOleDbConnection(ConnString))
  72. {
  73. OleDbCommand cmd = newOleDbCommand(
  74. "update [user] set name=@name,deptId=@deptid where Id=@id", conn);
  75. cmd.Parameters.Add("@name", OleDbType.Integer).Value = user.Name;
  76. cmd.Parameters.Add("@deptid", OleDbType.Integer).Value = user.DeptId;
  77. cmd.Parameters.Add("@id", OleDbType.Integer).Value = user.Id;
  78. conn.Open();
  79. returncmd.ExecuteNonQuery() == 1;
  80. }
  81. }
  82. }
  83. }

  后臺的testdb.mdb截圖:


當前題目:數據訪問層DAL實現(xiàn)過程
文章鏈接:http://m.5511xx.com/article/ccchgec.html