这更像是一个设计问题。
我正在建立一个应用程序,我创建了我的存储库模式结构,如下所示:
我的核心名称空间是DAL / Repository / BusinessLogic图层程序集。
顺便说一下,我使用Dapper.NET micro ORM作为我的数据连接,这就是为什么你会在我的SqlConnection对象上看到扩展名。
对于我的数据访问,我创建了一个基本存储库类:
namespace Core
{
public class BaseRepository<T>: IDisposable where T : BaseEntity
{
protected SqlConnection conn = null;
#region Constructors
public BaseRepository() : this("LOCAL")
{
}
public BaseRepository(string configurationKey = "LOCAL")
{
conn = new SqlConnection(ConfigurationManager.ConnectionStrings[configurationKey].ConnectionString);
}
#endregion
#region IDisposable
public void Dispose()
{
conn.Dispose();
}
#endregion
/// <summary>
/// returns a list of entities
/// </summary>
/// <typeparam name="T">BaseEntity type</typeparam>
/// <param name="sproc">optional parameters, stored procedure name.</param>
/// <returns>BaseEntity</returns>
protected virtual IEnumerable<T> GetListEntity(string sproc = null)
{
string storedProcName = string.Empty;
if (sproc == null)
{
storedProcName = "[dbo].sp_GetList_" + typeof(T).ToString().Replace("Core.",string.Empty);
}
else
{
storedProcName = sproc;
}
IEnumerable<T> items = new List<T>();
try
{
conn.Open();
items = conn.Query<T>(storedProcName,
commandType: CommandType.StoredProcedure);
conn.Close();
}
finally
{
conn.Close();
}
return items;
}
}
}
对于我拥有的每个实体,让我们说ExtendedUser,Messages,我在这样的Interface-Class对上创建它:
namespace Core
{
public class ExtendedUserRepository : BaseRepository<UsersExtended>,IExtendedUserRepository
{
public ExtendedUserRepository() : this("PROD")
{
}
public ExtendedUserRepository(string configurationKey) : base(configurationKey)
{
}
public UsersExtended GetExtendedUser(string username)
{
var list = GetListEntity().SingleOrDefault(u => u.Username == username);
return list;
}
public UsersExtended GetExtendedUser(Guid userid)
{
throw new NotImplementedException();
}
public List<UsersExtended> GetListExtendedUser()
{
throw new NotImplementedException();
}
}
}
等
上面的代码只是其中一个实体:ExtendedUser。
问题是:我应该为每个实体创建一个Interface-ClassThatImplemenetsInterface对吗?或者我应该只有一个RepositoryClass和一个IRepository接口以及我所有实体的所有方法?
答案 0 :(得分:1)
我认为你不需要在没有原因的情况下创建界面。我甚至不明白你为什么需要基础知识库类。我甚至认为这不是存储库,而是DAL(数据访问层),但这是一个明确的争论。
我认为良好的DAL实现应该将数据库结构与业务逻辑结构分离 - 但硬编码sp_GetList_XXXEntityNameXXX模式或在DAL之外传递存储过程名称并不是解耦。
如果您认为所有实体列表都是以一种方式获得的,并且您将始终需要业务逻辑中没有任何参数的完整实体集,那么您非常乐观或者您的应用程序非常简单。
只有在计划替换/包装不同的实现或在一个类中混合少量接口时,才需要将接口与实现分开。否则不需要。
在创建存储库时,不要考虑实体。存储库包含业务逻辑,应该在使用场景上构建。拥有类似于您的类更多是关于数据访问层 - 而DAL是基于业务逻辑中需要的查询构建的。可能你永远不会需要所有用户列表 - 但通常需要活跃用户列表,特权用户等。
很难预测你需要什么样的查询 - 所以我更喜欢从业务逻辑开始设计并顺便添加DAL方法。
答案 1 :(得分:1)
具有复杂域模型的系统通常受益于层,例如 作为Data Mapper(165)提供的那个,它隔离了域对象 从数据库访问代码的详细信息。在这样的系统中它可以 值得在映射上构建另一层抽象 查询构造代码集中的层。
使用通用存储库,您可以使用常见方法,例如findBy(array('id' => 1))
,findOneBy(array('email' => 'john@bar.com'))
,findById()
,findAll()
等。实际上,它将有一个界面。
您将始终必须创建一个具体实现,该实现将指示哪个是将由存储库管理的域对象,以实现此目的getUsersRepository().findAll()
此外,如果您需要更复杂的查询,可以在具体实现上创建新方法,例如findMostActiveUsers()
,然后在整个应用程序中重复使用。
现在,回答你的问题:
您的应用程序将至少期望一个接口(通用方法)。但是如果你设法有特定的方法,比如我上面提到的方法,你最好有另一个接口(例如RepositoryInterface和UsersRepositoryInteface)。
考虑到这一点,那么您将只依赖于存储库接口。查询构造将由具体实现封装。因此,您将能够更改存储库实施(例如,使用完整的ORM),而不会影响应用程序的其余部分。