So what did I just do here was to make the interface non-generic and move the generic type to the methods. Imagine now how easy is to do nextfollowing
public class RemindersService
{
private readonly IRepositoryBase _repository;
private readonly IUnitOfWork _unitOfWork;
public RemindersService(IRepositoryBase repository, IUnitOfWork uow)
{
_repository = repository;
_uow = uow
}
public Reminder AddNewReminder(DateTime moment, string note, Guid receiver, string name)
{
var user = _repository.FindById(receiver);
var reminder = new Reminder {ReceiverId = receiver, Moment = momoent, Note = note };
_repository.Create(reminder);
_uow.Save();
}
}
The main gain here is for very simplistic CRUD operations you don't need to create an interface and an implementation for you everyeach of entity fromin the DbContext.
Let's move next to the more specific repository. With the non-generic IRepositoryBaseIRepositoryBase it will look like this:
You have two options: either remove the interface inheritance or remove the the CreateReminder. If you remove the inheritance and keep the CreateXXX methods then you transmit the idea that the those XXXs are not handled as everything else by the repository, but the have a custom logic. I doubt that, since the repositories need to take care only for the store access. So remove these methods and let only the GetByName in the IReminderRepository. You might also decide to remove the interface inheritance and IRepositoryBase<Reminder> when you need those generic methods and IReminderRepository when you need the GetByName method.
SoLike I said you don't need to tie the UoW with the repositories interfaces. Follow this convention with the Repository suffix and you'll be fine to discover the repositories you need. OneOnce you have that, there is no need to transform the UoW into a ServiceLocator - Repositories FactoriesFactory.
Which brings the next: use an IoC for you dependencies. .Net Core? - built in. .Net Framework: a bunch of them. Still WebForms? There useUse Property Injection. So avoid newing your dependencies.
It's a repository, by defintion: Mediates between the domain and data mapping layers using a collection-like interface for accessing domain objects.
Take a look at the IListIList API and you'll find better naming:
Use this API as EntityFramework provides the asynchronous way to handle the databases. You'll be scalable, your threads you will be free to do something else (like handling new requestrequests) and won't be blocked until the SQL Server decides to returns its results.
The FindAll returns an IList which means the DbContext will send the query to the SQL server and then will map the results to the Reminder objects. After that the ReminderRepository object will search this in memory collection for the first reminder. What if you have 100.000 reminders? Probably you don't want to do thisthat, but to generate the SQL that will have in it the WHERE clause. So avoid ToList().FirstOrDefault() or any indirection to that if you know you will need just a subset of these records/objects.
IList has methods like Remove, Clear etc. Most likely the repository clients won't need that and even if they use them, the outcome won't be the expected one. The FindAll should return something that with youthey can only iterate/read. So use IReadonlyCollection.
The FindByCondition has the drawback that you'll looselose some encapsulation and abstraction and you open the gate for code duplication. I personally like it, but if I see that I tend to copy the predicate in a new place, then II'll add a new method in the repository, like you just did with FindByName. People are usually lazy (including myself) and sooner or later you'll get in trouble with it.