2014-04-23 115 views
1

我一直在努力DDD幾個月了,雖然我認爲我對某些概念有一個相當不錯的想法,但我對實現應該如何工作不太確定,特別是我該如何應對從數據庫加載數據。這並沒有幫助我只用C#工作了六個月。域驅動設計中的存儲庫

[原來的問題 - 見下方更新]

在我開始工作的應用程序,我有一個包含基類,執行使用這些基類操作的服務命名空間的域命名空間,並然後存儲庫和DAL命名空間連接到數據庫。

我認爲最簡單的方法是使用服務命名空間中的繼承來添加像LoadFromDb這樣的過程,但是當我開始實現時,我發現這個方法通常需要最多的代碼,因爲我必須將所有類屬性兩次(一次在存儲庫名稱空間中,然後在服務名稱空間中)。

下面是一個例子。我可以選擇2和方案3的工作,但我希望的東西,在精神上更接近選項1

namespace Domain 
{ 
    public class Request 
    { 
     public int RequestID{get; set;} 
     public string RequestingUser {get; set;} 
     public string Title {get; set;} 
     public string Description{get; set;} 
     public string status {get; set;} 
    } 
} 


namespace app 
{ 
    class MyApp 
    { 
     void Main() 
     { 
      //option 1 
      Domain.Request x = new Service.svcRequest(5); 

      //option 2 
      Domain.Request y = new Service.svcRequest(5); 

      //option 3 
      Domain.Request z = new Domain.Request(); 
      Service.svcRequest2.loadRequest(5, z); 
     } 
    } 
} 

namespace Service 
{ 
    public class svcRequest : Domain.Request 
    { 
     public svcRequest(int RequestID) 
     { 
      //this is what I want to do. 
      // It fails because "this" is read-only 
      // and because "this" can't be implicitly converted to DomainRequest. 
      this = (Domain.Request)repos.Loads.LoadRequest(RequestID); 

      //option 2, which is what I'm doing instead for now, but when you get 
      // to 20 or 50 properties, it's a bit much, 
      // esp. since those properties have already been assigned once 
      // within the repository namespace. 
      Domain.Request MyRequest = repos.Loads.LoadRequest(RequestID); 
      this.RequestID = MyRequest.RequestID; 
      this.RequestingUser = MyRequest.RequestingUser; 
      this.Title = MyRequest.Title; 
      this.Description = MyRequest.Description; 
      this.status = MyRequest.status; 
     } 
    } 

    public class svcRequest2 
    { 
     //option 3. Much less code, but now I'm not really using inheritance, 
     // so in my application layer I can't just declare my variable 
     // and use the svcRequest constructor 
     public static void loadRequest(int RequestID, Domain.Request MyRefRequest) 
     { 
      MyRefRequest = (Domain.Request)repos.Loads.LoadRequest(RequestID); 
     } 
    } 
} 

namespace repos 
{ 
    public static class Loads 
    { 
     public static Domain.Request LoadRequest(int RequestID) 
     { 
      Domain.Request MyRequest = new Domain.Request(); 
      DataRow MyRow = dal.Loads.LoadRequestRow(RequestID); 
      MyRequest.RequestID = RequestID; 
      MyRequest.RequestingUser = (string)MyRow["User"]; 
      MyRequest.Title = (string)MyRow["Title"]; 
      MyRequest.Description = (string)MyRow["Description"]; 
      MyRequest.status = (string)MyRow["Status"]; 
      return MyRequest; 
     } 
    } 
} 

namespace dal 
{ 
    public static class Loads 
    { 
     public static DataRow LoadRequestRow(int RequestID) 
     { 
      OleDbConnection dbCon = new OleDbConnection("Provider=SQLOLEDB;Data Source=dbServer;Initial Catalog=RequestDB;User ID=Joe;Password=password"); 
      string Select = "Select * from RequestTable where ID = " + RequestID; 
      OleDbDataAdapter dbRequest = new OleDbDataAdapter(Select, dbCon); 
      DataSet dsRequest = new DataSet(); 
      dbRequest.Fill(dsRequest); 
      DataRow drRequest = dsRequest.Tables[0].Rows[0]; 
      return drRequest; 
     } 
    } 
} 

[更新] 這裏的第二次嘗試。我將我的Domain名稱空間重命名爲Model,並將我的Service名稱空間重命名爲Domain,我認爲這更符合DDD約定。正如所建議的那樣,我在DAL中使用的存儲庫名稱空間中添加了一個接口。我現在唯一無法工作的是選項1的Load語句,但我認爲我只需要更多地研究繼承。

我靠得更近嗎?

using System; 
using System.Data; 
using System.Data.OleDb; 

namespace Model 
{ 
    public class Request 
    { 
     public int RequestID{get; set;} 
     public string RequestingUser {get; set;} 
     public string Title {get; set;} 
     public string Description{get; set;} 
     public string status {get; set;} 
    } 
} 


namespace App 
{ 
    class MyApp 
    { 
     void Main() 
     { 
      //option 1 
      Model.Request x = new Domain.dmnRequest(5); 

      //option 2 
      Model.Request y = new Domain.dmnRequest2(5); 

      //option 3 
      Model.Request z = new Model.Request(); 
      Domain.dmnRequest3.loadRequest(5, z); 
     } 
    } 
} 

namespace Domain 
{ 
    public class dmnRequest : Model.Request, dal.Request 
    { 
     public dmnRequest(int requestID) 
     { 
      //this is what I want to do. I'm not sure why it's failing 
      Load(requestID); 
     } 
    } 

    public class dmnRequest2 : Model.Request 
    { 
     public dmnRequest2(int requestID) 
     { 
      //option 2; it works but is cumbersome after you hit the 20th property 
      dal.Request tmpRequest = new dal.Request(); 
      tmpRequest.Load(requestID); 
      this.RequestID = tmpRequest.RequestID; 
      this.RequestingUser = tmpRequest.RequestingUser; 
      this.Title = tmpRequest.Title; 
      this.Description = tmpRequest.Description; 
      this.status = tmpRequest.status; 
     } 
    } 

    public class dmnRequest3 
    { 
     //option 3. Much less code, but now I'm not really using inheritance, so in my application layer I can't just declare my variable and use the dmnRequest constructor 
     public static void loadRequest(int RequestID, Model.Request MyRequest) 
     { 
      dal.Request dalRequest = (dal.Request)MyRequest; 
      dalRequest.Load(RequestID); 
      MyRequest = (Model.Request)dalRequest; 
     } 
    } 
} 

namespace repos 
{ 
    public interface SaveMe {void Save(int ID); } 
    public interface LoadMe {void Load(int ID); } 
} 

namespace dal 
{ 
    public class Request : Model.Request, repos.LoadMe 
    { 
     public void Load(int requestID) 
     { 
      OleDbConnection dbCon = new OleDbConnection("yaddayadda"); 
      string Select = "Select * from RequestTable where ID = " + requestID.ToString(); 
      OleDbDataAdapter dbRequest = new OleDbDataAdapter(Select, dbCon); 
      DataSet dsRequest = new DataSet(); 
      dbRequest.Fill(dsRequest); 
      DataRow drRequest = dsRequest.Tables[0].Rows[0]; 
      this.RequestID = requestID; 
      this.RequestingUser = (string)drRequest["User"]; 
      this.Title = (string)drRequest["Title"]; 
      this.Description = (string)drRequest["Description"]; 
      this.status = (string)drRequest["Status"]; 
     } 
    } 
} 

回答

3

你明白了。在DDD中,事情很簡單。該域只知道存儲庫接口,它由持久層(DAL)中的實際存儲庫類實現。該存儲庫與數據庫一起工作以保存/加載域對象(在DDD中,這些域對象應該是聚合根)。

這裏沒有什麼應該是靜態的,存儲庫應該從數據庫獲取所需的所有數據,然後使用它來恢復對象。存儲庫總是返回一個域實體,而不是數據行,數據表,實體框架實體等。這是因爲存儲庫的目的是將域與持久性細節分離。

簡而言之,該域名只是說:「嘿知識庫給我這個BsuinessEntity這個ID」。該域告訴存儲庫得到什麼,從來沒有如何得到它。該域名並不真正知道涉及到數據庫。它看到它是一個抽象(存儲庫接口),處理Domain知道的對象。

所有這一切都是爲了尊重分離關注。 Domain關心業務概念和用例,而存儲庫關心從數據庫中存儲/檢索對象。

+0

感謝您的回覆。你給了我很多想法。 – Jon