2009-07-19 68 views
1

理想情況下,我希望將所有代碼從數據庫中的數據存取到單獨的實用程序文件中,並將所有這些方法在數據綁定時從.NET代碼背後文件。問題出現在應該關閉連接對象的時候。對於簡單的東西,輔助方法可以關閉連接,但對於像DataGrid或GridView這樣的東西,只有在將數據綁定到GridView之後,才能關閉連接......所以我怎樣才能以最好的設計方式做到這一點?如果我有一流的呼叫DatabaseHelper,它有一個像 公共靜態數據集fetchEmployeesData .... 的方法這種方法不能關閉連接在ASP.NET中編寫數據訪問的最佳實踐

  • 我的另一個問題是如何使用的交易並做原子操作..例如,如果我有我的db helper類中的3或4方法說InsertX,InsertY,UpdateZ等,我必須調用一個事務中的所有這些操作,我如何編寫這樣的代碼與一個好的設計.. (在這個例子中,我會從aspx代碼後面的文件中調用這些方法)我的事件說表格提交)
  • +0

    爲了把細點對我的評論如下,你爲什麼要綁定到一個DataReader,而不是改變着的DataReader到一些中介對象第一?優化? – 2009-07-20 17:20:35

    回答

    1

    如果你只需要顯示數據,你確實可以在數據綁定之前關閉連接。 GridView僅要求您提供可枚舉的對象(即實現IEnumerable的對象),因此歡迎在呼叫DataAdapter.Fill後關閉連接 - 在綁定時不需要連接DataSet

    所以,一旦您撥打Fill - 可能在fetchEmployeesData之內 - 您可以關閉連接。如果fetchEmployeesData方法需要調用者提供的連接,可以在呼叫後關閉該方法:

    DataSet employeesDataSet = null; 
    using (IDbConnection connection = DatabaseHelper.CreateConnection()) { 
        employeesDataSet = DatabaseHelper.fetchEmployeesData(connection); 
    } 
    
    // The connection is closed now (since 'using' guarantees Dispose() is called) 
    EmployeeDataGridView.DataSource = employeesDataSet; 
    EmployeeDataGridView.DataBind(); 
    
    +0

    如果我使用DataReader而不是DataSet綁定網格,那麼我無法關閉連接,直到我綁定了網格。 – user133371 2009-07-19 18:57:54

    +0

    這是正確的,儘管有很多很好的理由可以將數據從DataReader中取出並且到一箇中間數據結構(一個數據集,一個列表等),主要是因爲你想盡快關閉這個連接。 – 2009-07-19 19:24:01

    3

    建議:不要重新發明輪子。

    {拉從烤箱中烤全輪}

    在這裏你去:Data Access Application Block Streamlines Your Data-Access Layer

    +0

    BTW:這個應用程序塊也非常優雅地處理交易問題。我已經將它用於許多應用程序,只需很少的修改(主要是改進了錯誤處理)。 – JohnFx 2009-07-19 18:26:12

    +0

    即使在這種情況下,使用數據訪問庫的代碼必須在某些Util類中,並且會遭受同樣的問題,例如使用DataReader for GridView以及事務處理,我們遇到同樣的問題 – user133371 2009-07-19 19:19:45

    2

    我一般建議是把所有的數據訪問到一個單獨的類(通常稱爲存儲庫)。如果你想讓自己的生活更輕鬆,那就去抓一個ORM來爲你做映射。如果你正在訪問SQL Server,Linq To SQL是很好的(而不是死掉的)。 Entity Framework,SubSonic,NHibernate,LLBLGen都運行良好。 (注意:NHibernate是我最喜歡的,但是如果你沒有人關閉,你可以問問題,去另一個ORM)。

    然後,ORM將爲您處理連接,並將使您的CRUD訪問變得更容易。

    完成後,您可以映射到您的數據訪問類。您可以直接綁定到DataGrid中的列表。

    0

    我的方法與Chris'類似。我可以補充的是,在DAL內部,只要完成數據操作,就應該打開並關閉連接。這增加了可伸縮性,並且在連接池方面仍然表現良好。

    將多個操作組合成單個事務時,我將使用System.Transactions命名空間中的TransactionScope。您還需要添加對System.Transactions.dll的引用。下面是關於如何這可能工作的一些僞代碼:

    using (var txScope = new TransactionScope(TransactionScopeOption.Required)) 
    { 
        InsertX... 
        InsertY... 
        InsertZ... 
    
        txScope.Complete(); 
    } 
    

    請記住,你的交易範圍完成(通常爲最後一條語句)調用。否則,事務將自動回滾(首次使用TransactionScope時常見的gottcha)。

    0

    你都應該儘可能晚地打開連接,並儘快將其關閉。所以我通常有返回DataTable,看上去就像一個方法:

    public DataTable GetUsersRightsForProject(int ProjectId) 
         { 
          SqlCommand cmd = GetNewCmd("dbo.GetUsersRightsForProject"); 
          cmd.Parameters.Add("@ProjectId", SqlDbType.Int).Value = ProjectId; 
          return GetTable(cmd); 
         } 
    

    的GetTable是,我用我所有的項目我的基類的方法。

    protected DataTable GetTable(SqlCommand objCmd) 
         { 
          DataTable dt = new DataTable(); 
          SqlDataAdapter da = new SqlDataAdapter(); 
    
          try 
          { 
           da.SelectCommand = objCmd; 
           da.Fill(dt); 
          } 
          catch (Exception ex) 
          { 
           LogException(ex); 
           throw ex; 
          } 
          finally 
          { 
           Close(objCmd); 
           da.Dispose(); 
           da = null; 
    
          } 
    
          return dt; 
    
         } 
    

    請注意,我儘可能晚地打開連接 - da.Fill(dt)實際打開並關閉它。然後我再次檢查它是否在「最後」部分關閉。我的基類需要得到連接字符串,記錄任何異常的照顧和我有類似這樣的一個GetDataSet,包裝的ExecuteScalar等

    所以,我可以綁定到這樣一個GridView:

    GridView1.DataSource = cApp.DB.GetUsersRightsForProject(ProjectId); 
    GridView1.DataBind(); 
    

    (通常你在中間的那個業務對象。)

    我的模式通常是:

    1. 創建新表。
    2. 創建存儲過程以獲取數據和保存數據。
    3. 創建調用存儲過程的數據訪問層方法(如上面的第一種方法)。

    這些編碼的一些可能是單調乏味的,特別是如果你的表有很多列。所以我寫了2個存儲過程來幫助解決這個問題。根據表生成一個「保存」存儲的proc代碼。第二個基於存儲的proc生成數據訪問方法代碼。

    他們可以發現here