軟體設計:DAO層該如何設計

來源:互聯網
上載者:User

關於Dao層的設計我現在也還是有點模糊,大大小小的項目也做了五六個了,負責的資料庫設計也有三四個了。

在對Dao層進行設計時採用過兩種方案:

  方案一:每一表對應一個Dao類(介面也可),每個Dao將完成對該表的增刪改查以及業務上要求的查詢操作。這麼設計的話如果表很多的話將會產生很多類,並且將會出現大量重複的代碼,因為每一個Dao中都將涉及到基礎的增刪改查。

  方案二:寫一個基礎的類,可以完成基本的增刪改查,其他的對於業務上有額外需求的表單獨在寫一個類,不過這個類只包括額外的功能。這裡的基礎類寫的時候是需要嚴格注意的,因為採用的類似映射的實現,需要你把實體類設計的同表結構一摸一樣,因為在該類中對資料庫的增刪改查的Sql語句就是通過對實體類類名以及對實體類類中屬性的提取完形成的。

  這裡給出一個基本的添加方法(vb.net實現):

Public Class SqlDao : Implements Dal.IDao

        Private SqlDr As SqlDataReader
        Private SqlCon As SqlConnection
        Private SqlCmd As SqlCommand
        '從設定檔app.config中取得串連資料庫的字串
        Private strConnect As String = ConfigurationManager.AppSettings("strCon")
        '得到類名
        Private strClassName As String
        '得到類的類型
        Private mType As Type
        '得到屬性集
        Private mProS As PropertyInfo()

        '在初始化方法中串連資料庫
        'Public Sub Init(ByVal obj As Object) Implements IDao.Init
        '    SqlCon = New SqlConnection(strConnect)

        '    '在建構函式中對必要類型進行初始化
        '    strClassName = TypeName(obj)
        '    mType = obj.GetType()
        '    mProS = mType.GetProperties
        'End Sub

        '串連資料庫的一個私人方法
        Private Function GetCon() As SqlConnection Implements IDao.GetCon
            Try
                If (SqlCon.State = ConnectionState.Closed) Then
                    SqlCon.Open()
                End If
            Catch ex As Exception
                MsgBox("開啟資料庫時:" + ex.Message)
            End Try

            Return SqlCon
        End Function

        ''' <summary>
        ''' 將對象添加到對應的表中,參數為對象,傳回值為Int型,表示影響的行數
        ''' </summary>
        ''' <param name="Entity "></param>
        ''' <returns>Integer</returns>
        ''' <remarks></remarks>
        Public Function AddObj(Of T)(ByVal Entity As T) As Integer Implements IDao.AddObj
            Dim res As Integer = 0 '用來返回該操作影響的行數
            '定義單個屬性
            Dim mPro As PropertyInfo
            '定義sql參數
            Dim para As SqlParameter
            Dim strFields As String = ""
            Dim strCondition As String = ""
            Dim strSql As String = ""
            For Each mPro In mProS
                '該迴圈用來進行參數組合
                '再添加時不用添加時間
                strFields = CStr(Trim(mPro.GetValue(Entity, Nothing)))  '擷取屬性值
                If strFields <> "0" And strFields <> "00:00:00" And strFields <> "" Then

                    strSql = strSql + "@" + mPro.Name + ","
                    '組合形成欄位名
                    strCondition = strCondition + mPro.Name + ","
                End If
            Next
            '最後再插入最後的括弧

            strSql = Left(strSql, Len(strSql) - 1) + ")"
            strCondition = Left(strCondition, Len(strCondition) - 1) + ")"
            strSql = "INSERT INTO " + strClassName + " (" + strCondition + " VALUES (" + strSql
            'MsgBox(strSql)
            Try
                Using sCmd As New SqlCommand(strSql, GetCon)
                    '設定執行方式
                    sCmd.CommandType = CommandType.Text
                    For Each mPro In mProS
                        '進行參數的賦值
                        'Dim stra As String = mPro.GetValue(obj, Nothing)
                        '一般的添加不用加入時間,除了下機表
                        strFields = CStr(Trim(mPro.GetValue(Entity, Nothing)))  '擷取屬性值
                        If strFields <> "0" And strFields <> "00:00:00" And strFields <> "" Then
                            para = New SqlParameter("@" + mPro.Name, mPro.GetValue(Entity, Nothing))

                            sCmd.Parameters.Add(para)
                        End If
                    Next
                    res = sCmd.ExecuteNonQuery
                End Using
            Catch ex As Exception
                MsgBox("進行對象添加時:" + ex.Message)
            End Try
            Return res '返回該操作影響的行數
        End Function
End Class

  這幾天從網上也查了一些資料主要就是關於Dao層該如何設計的問題,最直接的設計方案就是每一個表對應一個Dao,說是代碼重複太多,不過這樣設計那些基本的代碼是不用寫的,都有現成的工具,直接根據表產生對應的增刪改查。

  不過因為需要重複的代碼太多了,因此有人提出這種方法:

    public interface BaseDao<T> {  
        public void create (T t);  
        public void delete (T t);  
        public void update (T t);  
    }  
      
    public interface WindDao extends BaseDao<Wind> {  
        public void other (Wind wind);  
    }

  將基本的增刪改查通過泛型放置到一個基礎的介面中,其他的只需實現該介面,如果有額外的需求便可自行添加方法。這可謂一個典型的繼承的應用。不過說實話,這種方法也不能使代碼量減少。

  這塊還真是不太明白,論壇裡有人說:“其實可以將basedao注入baseservice來實現,這樣就不用每個dao都寫一個類了”,實在是理解不了,如果有大牛恰好經過勞煩指點一二,不勝感激。

曹師哥點撥:

遇到一個問題,我會採用軟體工程上的3w原則(what,why,how)來思考。

首先what:

 

  • dao(data access object),Data Access Objects,既然是對象那麼就有封裝,他封裝了業務及相關資料與資料庫進行互動的一系列的介面。
  • why:

  • 1.使用者不需要瞭解這個對象細節,只需要瞭解這個對象的介面就可以資料庫進行互動,這樣方便了使用者的使用。
  • 2.設計一個dao層,上面所有的業務層都調用這個dao層的介面,這樣就實現了軟體的重用性。
  • 3.dao層的存在使得商務邏輯層跟訪問資料庫的代碼分開了。
  • 4.dao層可以處理不同資料庫的差異性,使得軟體在oracle,mysql,db2等資料庫上遷移時改變代碼很少。
  • 5.dao層的封裝不需要開發人員直接跟資料庫互動(有了dao層,通過dao層互動),增加了資料庫的安全性。等等
  • how:通過以上的why的分析,我們在設計dao層的時候,要注意:

  • 1.提供豐富的介面供使用者調用,
  • 2.在dao中不能涉及業務內容,一個dao層介面就對應一次資料庫操作(是原子性的)。
  • 3.考慮軟體在不通資料庫上的遷移。
  • 4.dao層是用來實現業務及相關資料和資料庫互動的橋樑,那麼dao層就需要對資料庫的操作進行一系列的封裝,包括增刪改查,資料庫的事務,預存程序,觸發器等等操作。其中有一點要注意的是事務的處理,dao層一般不負責事務的處理,把交易處理遺留給業務層來做。原因是:如果一次商務邏輯需要調用多個dao的方法,一旦某個dao的方法失敗,造成復原,則已經執行的那些DAO則無法復原。
  • 總之,使用dao層,使得業務的操作跟資料庫的操作進行瞭解耦,業務的變化不會影響資料的訪問,而資料訪問方式的改變(保證介面不變),不會影響業務,使得系統的各個部分相互獨立。dao層的操作是對業務的一個分解,把一個完整的業務分解到資料庫中的相關表中。

     

    原創文章,轉載請註明出處:http://www.the5fire.net/?p=168
    本文固定連結:the5fire的技術部落格 | 如果喜歡我的部落格的話可以訂閱本博以便及時收到更新

    相關文章

    聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.