【问题标题】:Passing DTO's to service layer for CRUD operations将 DTO 传递给服务层以进行 CRUD 操作
【发布时间】:2018-01-04 23:22:20
【问题描述】:

我正在开发一个 ASP.NET MVC Web 应用程序。 我目前的架构如下:

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

数据访问层包含 EF 实体模型。 服务层从数据访问层检索 EF 实体模型并返回 DTO。 表示层从服务层检索 DTO,并将 ViewModels 返回给 Views。

我的问题是我应该将什么类传递给驻留在我的服务层中的创建和更新函数。例如:

实体模型:

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 与 Entity 模型完全匹配,但是使用 DTO 有什么意义呢?
  2. 我可以使用 UserTypeDTO 类作为 UserDTO 的属性,而不是使用“平面”DTO。我认为这会让事情变得更清楚一些,但在调用 EditUser(UserDTO) 时仍然不需要设置它。 附带问题:关于 D​​TO 是否应该“平坦”是否有任何最佳实践?
  3. 还有其他想法吗...?

感谢您的帮助!!

【问题讨论】:

    标签: c# asp.net-mvc entity-framework mapping dto


    【解决方案1】:

    我建议对 Get 和 Edit 操作使用单独的 DTO 定义。那么消费者就不可能尝试设置他们不应该设置的东西。所以我会说在 EditUser 方法中使用EditUserDTO

    更新

    为我的答案添加更多上下文。

    使用 DTO 的想法是抽象出您的底层 DAL。通常有更多的数据存储在您的数据层中,这些数据不是从您的服务层返回的,或者您的实体可能与您想要发回给调用者的结构不同,因此通过创建 DTO,您可以隐藏它离开。这也使您可以选择更改 DAL 并保持服务层的公共合同不变,这样当您在内部更改某些内容时,消费者不必重新编写他们的代码。

    DTO 可以是扁平的或具有层次结构。这实际上取决于保持 DTO 平坦或具有层次结构是否有意义。以您的示例 UserDTO 为例,我想说除非您要在 UserDTO 中返回 UserTypes 树,否则您应该将其保留为简单的“平面”DTO。

    【讨论】:

    • 我同意您关于 DTO 提供的好处的所有陈述。我倾向于同意您关于使用单独的 DTO 进行获取和编辑的回答。我只是没有看到任何这样的完整例子。我看到的大多数示例都使用相同的 DTO,但示例中的 DTO 往往与实体模型完全匹配......碰巧知道@Darren 的任何示例或教程?
    • 最近我一直在研究一些 REST API。例如,DAL 返回有关用户个人资料的信息,包括分数、是否是经过验证的用户以及散列和加盐密码。当应用程序获得特定用户个人资料时,他们的当前分数和 bool 指示他们是否已通过验证,我们不会返回密码哈希,原因很明显。当用户编辑他们的个人资料时,服务不允许他们编辑他们的分数,或者他们是否经过验证,因为这些是应用程序使用或管理功能的产物。所以我们对这些使用单独的 DTO。
    • 希望有一个在线/物理示例,但轶事也可以:)。是的,我绝对看到在这种情况下单独的 DTO 是多么有意义。如果您不介意,我还有一个关于 DTO 的问题:stackoverflow.com/questions/45382492/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-06
    • 1970-01-01
    • 2013-04-19
    • 2014-08-28
    • 2013-03-12
    • 1970-01-01
    相关资源
    最近更新 更多