This is more of a design concern.
Im building an app and i have created my Repository Pattern Structure as following :
My Core name space is the DAL/Repository/BusinessLogic layers assembly.
By the way, i am using Dapper.NET micro ORM as my data connection, thats why you will see an extension on my SqlConnection object.
For my data access, i have created a base repository class :
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;
}
}
}
And for each entity that I have, lets say ExtendedUser, Messages , i am creating its on Interface-Class pair like this :
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();
}
}
}
etc.
The above code is just one of the entities :ExtendedUser.
The question is : should i create a Interface-ClassThatImplemenetsInterface pair for each entity that i have ? or should i have only one RepositoryClass and one IRepository interface with all my methods from all of my entities?
I don't think you need to create interface without the reason. I even don't see why you need base repository class here. I even think this is not repository but DAL (Data Access Layer) but this is defintion argue.
I think good DAL implementation should decouple database structure from business logic structure - but hardcoding sp_GetList_XXXEntityNameXXX pattern or passing stored procedure name outside of DAL is not decoupling.
You are very optimistic or your application is really simple if you think all entity lists are obtained in one way and you will always need full set of entities in business logic without any parameters.
Separating interface from implementation is only needed if you plan to replace/wrap out different implementations, or mix few interfaces in one class. Otherwise it is not required.
Don't think in terms of entities when creating repositories. Repository contains business logic and should be built over scenarios of usage. Having classes like you have is more about Data Access Layer - and DAL is built over queries you would need in business logic. Probably you would never need list of ALL users at once - but would very often need list of active users, privileged users etc.
It is really hard to predict what queries you will need - so I prefer to start designing from business logic and add DAL methods by the way.