我应该在Web API中使用DTO接口吗?

时间:2018-01-01 19:40:46

标签: c# asp.net-core

我正在使用.NET Core 2中的web api进行实验,我试着像以下示例中那样干净地分离问题:https://msdn.microsoft.com/en-us/magazine/mt703433.aspx

我想知道的一件事是:当使用存储库接口来设置/获取数据时,数据类型是否也应该是接口?

示例(缩小以强调问题):

public class ProjectController : Controller
{
    IProjectRepository _repo;

    [HttpGet]
    public IProject GetProject([FromRoute] string key)
    {
        return _repo.GetProject(key);
    }
}


public interface IProjectRepository
{
    IProject GetProject(string key);
}


// Implementation based on Entity Framework
public class EFProjectRepository : IProjectRepository
{
    private SomeEfContext _context;

    public IProject GetProject(string key)
    {
        return _context.Projects.SingleOrDefault(p => p.Key == key);
    }
}


public interface IProject
{
    string Key { get; set; }
    string Name { get; set; }
}


// EF specific implementation
public class Project : IProject
{
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }

    public string Key { get; set; }
    public string Name { get; set; }
}

我这样做的原因是,如果我不这样做,那么特定于EF实现的字段 Id 将会"流失"进入控制器,我不想要。正如我所说,这个例子非常简单,有这个Id字段存在的原因 - 当示例扩展到相关的DTO"任务"时,它变得更加明显。等

有更好的方法吗?

1 个答案:

答案 0 :(得分:4)

我还没有看过DTO界面,如果你有不同的客户端有共同的属性,你可以使用它。我看到的问题是您在实体(您的Business Objects)和DTO(您从客户端发送/接收的内容)之间混淆。
通常,作为客户端的Controller不会知道存储库层。这应该是服务层的知识 如果您只有一个使用Entity Framework的数据访问层,并且您不打算将其放在一边,我建议您根本不要使用Repository层,因为它已经实现了两个Repository({{1} })和工作单位(DbContext)。

标准的SOLID架构看起来像这样(每个都是一个单独的项目):

  • Project.Core
    • 每个人都可以看到
    • 不包含任何参考
    • 包含您的DTO和帮助程序类
  • Project.DataAccess
    • 可见域名
    • 包含您的EF内容
  • Project.Domain
    • 仅对Web配置DI
    • 可见
    • 参考核心
    • 接收并返回DTO
    • 这是您的业务逻辑实际上在哪里
  • Project.Abstractions
    • 可见网站和域名
    • 包含您的服务的接口,这些接口在域
    • 中实现
  • Project.Tests
    • 引用域和核心
    • 包含您的测试
  • Project.Web
    • 参考域,抽象和核心
    • 包含您的实际Web API
    • 使用依赖注入来调用域的服务。
    • 接收原语(DbSetstring等)或DTO,并返回DTO

请注意,只有域/业务层实际上会看到代表您的数据库的实体。