2017-07-28 44 views
2

我正在研究ASP.NET MVC Web應用程序。 我目前的架構是這樣的:將DTO傳遞給服務層進行CRUD操作

Presentation Layer <--> Service Layer <--> Data Access Layer 

數據訪問層包含EF實體模型。 服務層從數據訪問層檢索EF實體模型並返回DTO。 表示層從服務層檢索DTO,並將ViewModels返回到視圖。

我的問題是關於我應該將哪些類傳遞給駐留在我的服務層中的創建和更新函數。例如:

實體模型:

public class User 
{ 
    public int Id { get; set; } 
    public string FirstName { get; set; }  
    public string LastName { get; set; }    
    public int UserTypeId { get; set; } 

    public virtual UserType UserType { get; set; } 
} 

public class UserType 
{ 
    public int Id { get; set; } 
    public string Name { get; set; }     

    public virtual UserType UserType { get; set; } 
} 

DTO:

public class UserDTO 
{ 
    public int Id { get; set; } 
    public string FirstName { get; set; } 
    public string LastName { get; set; }     
    public int UserTypeId { get; set; } 

    //Note this "extra" field 
    public string UserTypeName { get; set; }   
} 

服務層功能:

public class UserService: IUserService 
{ 
    public UserDTO GetUser(int userId) 
    { 
     //The UserType.Name is used a lot, so I'd rather include it in this one db call 
     //rather than use a separate db call to get the name based on the UserTypeId 

     return _dbContext.Users.Where(u => u.Id == userId) 
        .Select(u => new UserDTO 
        { 
         Id = u.Id, 
         FirstName = u.FirstName, 
         LastName = u.LastName, 
         UserTypeId = u.UserTypeId, 

         UserTypeName = u.UserType.Name 
        } 
        .First(); 
    } 

    //?? 
    public void EditUser(UserDTO userDto) 
    { 
     //Should I use this? Or EditUser(EditUserDTO editUserDto)...  
    } 

    //?? 
    public void EditUser(EditUserDTO editUserDto) 
    { 
     //Should I use this? Or EditUser(UserDTO userDto)... 
     //Note EditUserDTO looks like UserDTO but does not have UserTypeName 
    } 
} 

你會看到我的困惑是因爲使用什麼類EditUser(...)的參數。

  • 如果我使用EditUser(UserDTO userDto),那麼如何將其他開發商 知道他們需要設置UserDTO.UserTypeName?他們 只需要設置UserTypeId。
  • 如果我使用EditUser(EditUserDTO editUserDto),那麼開發人員將知道 準確設置哪些信息(EditUserDTO中的每個屬性)。但它是一個額外的類來維護,映射和使用。

一些建議:

  1. 我能有DTO實體模型精確相符,但是那有什麼用DTO的意義呢?
  2. 而不是有一個「扁平」的DTO,我可以有一個UserTypeDTO類作爲UserDTO的一個屬性。我認爲這會讓事情變得更加清晰,但在調用EditUser(UserDTO)時仍然不需要設置。 側面問題:DTO是否應該是「平坦」的最佳做法?
  3. 任何其他想法...?

感謝您的幫助!

回答

1

我建議使用單獨的DTO定義進行獲取和編輯操作。那麼消費者就不可能設置他們不應該做的事情。所以我會說EditUser方法使用EditUserDTO

更新

要多一點背景添加到我的回答。

使用DTO的想法是將您的底層DAL抽象出來。通常有更多的數據存儲在您的數據層中,而不是從您的服務層返回,或者您的實體可能沒有您想要發送回調用者的相同結構,因此通過創建DTO,您可以隱藏這個遠。這也使您可以選擇更改DAL並保持服務層的公共契約相同,以便消費者在內部更改某些內容時不必重新編寫代碼。

DTO's可以是平坦的或有層次結構。這實際上取決於保持DTO是否平坦或具有層次結構是否合理。以您的示例UserDTO爲例,除非您要返回UserDTO中的UserTypes樹,否則您應該將其保留爲簡單的「扁平」DTO。

+0

我同意所有關於DTO提供的利益的陳述。我傾向於同意你關於使用單獨的DTO獲取和編輯的答案。我只是沒有看到像這樣的完整例子。我看到的大多數示例都使用相同的DTO,但示例中的DTO傾向於完全匹配實體模型.... 瞭解任何示例或教程@Darren? –

+0

最近我一直在研究一些REST API。例如,DAL返回有關用戶個人資料的信息,包括評分等內容,如果他們是經過驗證的用戶以及哈希和密碼。當應用程序獲得特定的用戶配置文件時,它們的當前分數和一個表示它們是否被驗證的「bool」被返回,我們不會因爲明顯的原因返回密碼哈希值。當用戶編輯他們的個人資料時,這些服務不允許他們編輯他們的分數,或者他們是否被驗證,因爲這些都是應用程序使用或管理功能的產品。所以我們爲這些使用單獨的DTO。 –

+0

希望得到一個在線/物理的例子,但一個軼事的例子:)。是的,我絕對看到在這種情況下單獨的DTO是多麼有意義。 如果您不介意,我還有另一個關於DTO的問題: https://stackoverflow.com/questions/45382492/validating-data-in-the-service-layer-against-dtos-entity-models-or-一些-E –