【问题标题】:Exposing Entity Framework extensions to a Service Layer向服务层公开实体框架扩展
【发布时间】:2017-03-24 17:23:20
【问题描述】:

我已经使用IRepository 模式实现了我的数据层。其中一种方法返回IQueryable

public virtual IQueryable<TEntity> Queryable()
{
        return dbSet;
}

我还有一个服务层,它调用这个提供过滤的方法,例如:

public User GetByName(string name)
{
    return _repository.Queryable()
        .Where(a => a.Name == name)
        .ToList();
}

到目前为止这么好,Entity Framework 只在数据层引用,Service 层对此一无所知。

现在,我想做两件事:

  1. 使用Include 方法
  2. 使用ToListAsync()方法

所以现在我的服务方法是这样的:

public async Task<User> GetByName(string name)
{
    return await _repository.Queryable()
        .Where(a => a.Name == name)
        .Include(x => x.Pets)
        .ToListAsync();
}

现在的问题是 Include()ToListAsync() 都在 System.Data.Entity 命名空间中,而 EntityFramework.dll 中。

我不想在我的服务层中引用 EF,它不应该关心或知道这一点,但在保持架构清洁的同时看不到如何解决这个问题。我能看到的唯一解决方案是:

  1. 将实体框架添加到服务层
  2. 向包装IRepository&lt;User&gt;' and handles the two additional methods required. The service will then take use an instance of this rather thanIRepository`的数据层(UserData)添加一个新类。

关于我如何在坚持最佳实践的同时解决这个问题有什么建议吗?

【问题讨论】:

  • 如果您只是要公开一个允许业务层编写自己的查询的调用,我真的不明白抽象出 EF 的意义。它让存储库对我来说有点毫无价值。与问题无关,我只是好奇那里的逻辑。
  • 我觉得Include 部分真的应该在存储库中。本质上,存储库应该知道根据对象图返回什么,并且这些操作应该简单地支持任何用例的业务需求。如果ToListAsync 在 EF 之外会很好,我同意。虽然我想我对它的实现知之甚少,不知道它在 EF 之外是否有意义。
  • 除了“最佳实践”之外,您为什么要使用存储库,原因是什么?也许您希望缓存结果或其他内容。
  • 即使有人有 gd 链接可供阅读,我也希望能对此进行更新。我发现我总是在有意义的事情之间纠结。

标签: c# entity-framework architecture n-tier-architecture


【解决方案1】:

我了解您希望根据最佳实践在存储库层中抽象出 EF。但是您的用例(您的主要问题)与此矛盾 - 您希望将 EF 提供的所有内容暴露给您的服务层。

听起来您需要对这个存储库的职责定义一个严格的界限。如果要返回IQueryable,那么包装EF 有什么好处呢?您是否计划在生产中实际使用其他一些存储库实现?如果是这样,当您公开IQueryable 时,将很难确保两种 repo 类型都是正确的。这就是你现在看到的痛点。

在我看来,存储库应该定义您获取数据的方式。它应该公开像GetAllUsers 这样返回实际模型的简单调用。当您让业务/服务层定义自己的方式来获取数据时,它会让存储库感觉多余。

【讨论】:

    【解决方案2】:

    Include 和 ToListAsync 存在于 EF 中,因此它们应保留在 EF 服务中。

    无需提供对 System.Entity 的引用即可访问它们的唯一方法是创建自己的代理方法。归根结底,您应该根据应用程序的高级需求进行编码,而不是确保它可以访问 EF 可以访问的所有内容。

    当我处理 EF 时,我创建了一个服务/上下文层、一个存储库层,然后是一个抽象出 EF 技术性的客户端层。然后这是其他开发人员/用户的用户,因此他们不会过多地暴露于 EF 方面。我只是锻炼应用程序所需的内容并实施方法来做到这一点,仅此而已。将 System.Entity 的功能带到 DAL 之外没有什么意义,它们应该在客户端级别抽象出来。

    我讨厌的一件事是如果我想让我的服务/上下文层远离应用程序的其他部分,就必须复制模型。为了解决这个问题,我有一个模型工厂,它使用 DI 来查找 EF 模型并通过 DI 容器交付它们。这只是意味着我必须为我创建的每个模型添加一个接口。没什么大不了的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-11
      • 2011-06-05
      • 2023-03-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多