我使用IRepository
模式实现了我的数据层。其中一种方法返回IQueryable
:
public virtual IQueryable<TEntity> Queryable()
{
return dbSet;
}
我还有一个Service层,它调用这个提供过滤的方法,例如:
public User GetByName(string name)
{
return _repository.Queryable()
.Where(a => a.Name == name)
.ToList();
}
到目前为止,实体框架只在数据层中被引用,服务层对此一无所知。
现在,我想再做两件事:
Include
方法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,它不应该关心或了解这一点,但是在保持架构清洁的同时无法看到如何解决这个问题。我能看到的唯一解决方案是:
UserData
IRepository`的数据层(IRepository<User>' and handles the two additional methods required. The service will then take use an instance of this rather than
)。关于如何在坚持最佳做法的同时解决这个问题的任何建议?
答案 0 :(得分:1)
据我所知,您希望根据最佳实践抽象出存储库层中的EF。但是您的使用案例(这里的主要问题)与此相矛盾 - 您希望公开EF为您的服务层提供的所有内容。
听起来您需要定义一个严格的关于此存储库的责任的行。如果它要返回IQueryable
,那么包装EF的好处是什么?您是否计划在生产中实际使用其他存储库实施?如果是这样,当您公开IQueryable
时,确保两种回购类型都是正确的将非常困难。这是你现在看到的痛点。
在我看来,存储库应该定义如何获取数据。它应该暴露像GetAllUsers
之类的简单调用来返回实际模型。当您让业务/服务层定义自己获取数据的方式时,它会使存储库感到多余。
答案 1 :(得分:0)
在EF中包含和ToListAsync,因此它们应保存在EF服务中。
访问这些而不必提供对System.Entity的引用的唯一方法是创建自己的代理方法。在一天结束时,您应该在高级别编写应用程序所需的代码,而不是确保它可以访问EF可以访问的所有内容。
当我处理EF时,我创建了一个服务/上下文层,一个存储库层,然后是一个客户层,它抽象出EF技术细节。然后,这是其他开发者/用户的用户,因此他们不会向EF方面暴露太多。我只是锻炼应用程序所需的内容并实现方法来做到这一点,仅此而已。将System.Entity的功能带到DAL之外没有什么意义,它们应该在客户端层面抽象出来。
我讨厌的一件事是,如果我想让我的服务/上下文层远离应用程序的其他部分,则必须复制模型。为了解决这个问题,我有一个模型工厂,它使用DI来找到EF模型并通过DI容器交付。这只意味着我必须为我创建的每个模型添加一个接口。没什么大不了的。