将DTO传递到服务层以进行CRUD操作

时间:2017-07-28 19:33:25

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

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

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. 我可以将UserTypeDTO类作为UserDTO的属性,而不是使用“平面”DTO。我认为这会使事情变得更加清晰,但在调用EditUser(UserDTO)时仍然不需要设置它。 附带问题:对于DTO是否应该“平坦”,是否有最佳做法?
  3. 还有其他想法......?
  4. 感谢您的帮助!!

1 个答案:

答案 0 :(得分:1)

我建议对Get和Edit操作使用单独的DTO定义。然后,消费者不可能尝试设置他们不应该做的事情。所以我会说使用EditUserDTO作为EditUser方法。

<强>更新

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

使用DTO的想法是抽象出你的潜在DAL。您的数据层中存储的数据通常不会从您的服务层返回,或者您的实体可能与您要发送回调用者的结构不同,因此通过创建DTO,您可以隐藏此数据远。这也为您提供了一个选项,您可以选择更改DAL并保持服务层的公共合同相同,以便消费者在内部更改内容时不必重新编写代码。

DTO可以是扁平的或具有层次结构。这实际上取决于保持DTO平坦或层次结构是否合理。以你的例子UserDTO为例,我会说,除非你要在UserDTO中返回UserTypes树,否则你应该把它作为一个简单的&#34; flat&#34; DTO。