业务逻辑层中的模型封装问题

时间:2019-05-22 22:06:25

标签: c# entity-framework oop asp.net-core

我有一个带有控制器,服务和存储库的典型应用程序。因此,有2个项目:

  • 带有控制器的ASP.NET Core WebAPI
  • 具有所有业务逻辑的核心

WebAPI应该只了解Core提供的服务。在Core中,我具有返回DTO的公共类(服务),但是这些服务取决于我要标记为internal的DbContext。我当然不能

  

错误CS0051可访问性不一致:参数类型   “ DevicesDbContext”比方法更难访问   'DeviceService.DeviceService(DevicesDbContext,IMapper)'

我正在使用EF Core和instead of own Repositories I use DbContext。我有仅在Core项目中必须使用的实体模型。您能建议我如何实现吗?

例如,我的模型是:

internal class Device
{ 
   public int Id {get;set;}
}

DbContext:

internal class DevicesDbContext : DbContext
{
   public DbSet<Device> Devices {get;set;}
}

服务:

public class DeviceService : IDeviceService
{
   public DeviceService(DevicesDbContext dbContext, IMapper mapper)
   { 
   }
   ..
}

我在DeviceService的构造函数中遇到了该错误。它不是duplicate,因为我知道该错误的含义以及解决方法。在这里,我询问了这种方法的设计或体系结构,因为我需要避免直接在WebAPI中使用模型和dbcontext

1 个答案:

答案 0 :(得分:1)

如果您不想使用存储库来保护数据访问(通常仍返回实体,而不是DTO,则实体需要公开),那么真正的问题是: “为什么要避免在Web API中使用DbContext和实体?”

实体框架是一个框架。目的是促进数据访问,使您的代码更易于编写和理解。正如您选择使用.Net框架并通过选择EF来利用Linq,Generics等工具一样,您也应该尝试利用它提供的所有功能。

如果绝对必须将上下文和实体保留在API程序集引用之外,或者要集中涉及Web API与另一组MVC控制器之间的实体的业务逻辑,那么您正在考虑构建一个贫乏的API。在这种情况下:

Services.DLL-引用DbContext,实体。

public interface ISomethingService
{
  IEnumerable<SomeDto> GetSome(/*params*/);
}

public class SomethingService : ISomethingService
{
    public SomethingService(SomeDbContext context) 
    { // Init stuff. 
    }

    IEnumerable<SomeDto> ISomethingService.GetSome()
    {
       // Get some stuff and return DTOs.
    }
}

Web API DLL-仅引用DTO。

public class SomeAPI : ISomethingService
{
    private ISomethingService Service { get; set; }
    public SomeAPI(ISomethingService service)
    {
        Service = service;
    }

    public IEnumerable<SomeDto> GetSome()
    {
        return Service.GetSome();
    }
}

API是贫乏的,因为它只是将请求传递到公共服务并转发响应。该API不需要实现相同的接口,它可以简单地接受对服务的引用并使用它,并通过任何参数来获取将传递回的DTO。

此方法的缺点是,要修改在API和服务层之间切换的服务,而不是仅在API中工作。我不喜欢使用这样的方法,因为API等通常需要考虑过滤,分页等细节,因此我想利用EF提供的出色的LINQ功能。我还充分利用了EF的IQueryable支持来保持我的数据访问层简单而紧凑,让消耗性服务决定如何获取所需的细节。用额外的服务边界来掩盖它会增加复杂性和低效率,因为这会导致代码复杂,功能非常相似,并且/或者浪费了内存/处理以返回不需要的数据。