C# 向服务层公开实体框架扩展

C# 向服务层公开实体框架扩展,c#,entity-framework,architecture,n-tier-architecture,C#,Entity Framework,Architecture,N Tier Architecture,我已经使用IRepository模式实现了我的数据层。其中一个方法返回一个IQueryable: public virtual IQueryable<TEntity> Queryable() { return dbSet; } 到目前为止,实体框架只在数据层中引用,服务层对此一无所知 现在,我想做两件额外的事情: 使用Include方法 使用ToListAsync()方法 现在我的服务方法如下所示: public async Task<User> Get

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

public virtual IQueryable<TEntity> Queryable()
{
        return dbSet;
}
到目前为止,实体框架只在数据层中引用,服务层对此一无所知

现在,我想做两件额外的事情:

  • 使用
    Include
    方法
  • 使用
    ToListAsync()
    方法
  • 现在我的服务方法如下所示:

    public async Task<User> GetByName(string name)
    {
        return await _repository.Queryable()
            .Where(a => a.Name == name)
            .Include(x => x.Pets)
            .ToListAsync();
    }
    
    公共异步任务GetByName(字符串名称)
    {
    return wait_repository.Queryable()
    .Where(a=>a.Name==Name)
    .包括(x=>x.Pets)
    .ToListAsync();
    }
    
    现在的问题是
    Include()
    ToListAsync()
    都位于
    System.Data.Entity
    命名空间中,该命名空间位于
    EntityFramework.dll

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

  • 将实体框架添加到服务层
  • 向数据层(
    UserData
    )添加一个新类,该类包装了
    IRepository”,并处理所需的两个附加方法。然后,服务将使用此实例,而不是
    IRepository`

  • 关于如何在坚持最佳实践的同时解决此问题的任何建议?

    包括和ToListSync live in EF,因此应将其保留在EF服务中

    不必提供对System.Entity的引用就可以访问这些方法的唯一方法是创建自己的代理方法。在一天结束时,你应该在一个较高的层次上编写你的应用程序所需要的代码,而不是确保它可以访问EF所能访问的一切

    当我处理EF时,我创建了一个服务/上下文层、一个存储库层,然后是一个客户机层,它抽象出EF技术细节。然后由其他开发人员/用户使用,这样他们就不会太多地暴露在事件的EF端。我只是锻炼了应用程序所需要的东西,并实现了一些方法来完成这一点,仅此而已。将系统实体的功能引入DAL之外没有什么意义,它们应该在客户机级别抽象出来


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

    我知道您希望基于最佳实践在存储库层抽象出EF。但是您的用例(这里的主要问题)与此相矛盾-您希望将EF提供的所有内容公开给您的服务层

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


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

    如果您只是想公开一个允许业务层编写自己的查询的调用,那么我真的不理解抽象EF的意义。这让我觉得存储库毫无价值。与这个问题没有太大关系,我只是想知道其中的逻辑是什么。我觉得
    Include
    部分真的应该在存储库中。本质上,存储库应该知道根据对象图返回什么,这些操作应该只支持任何用例的业务需求。如果
    ToListAsync
    在EF之外,那就太好了,我同意。虽然我想我对它的实现了解不够,不知道它在EF之外是否有意义。除了“最佳实践”之外,为什么要使用存储库,原因是什么?也许您希望缓存结果或其他东西。。你也可以添加对EF的引用。即使有人有gd链接要读,你也会喜欢这方面的更新。因为我发现我总是在有意义的东西之间徘徊。
    public async Task<User> GetByName(string name)
    {
        return await _repository.Queryable()
            .Where(a => a.Name == name)
            .Include(x => x.Pets)
            .ToListAsync();
    }