I am trying to build a structure using repository pattern in entity framework core.
I have an generic interface and a service for general operations. They simply do CRUD transactions.
My interface:
public interface IGeneralService<TEntity> where TEntity : class
{
void Delete(TEntity entityToDelete);
void Delete(object id);
IEnumerable<TEntity> Get(
Expression<Func<TEntity, bool>> filter = null,
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
string includeProperties = "");
TEntity GetById(object id);
void Insert(TEntity entity);
void Update(TEntity entityToUpdate);
}
My service Layer:
public class GeneralService<TEntity> : IGeneralService<TEntity> where TEntity : class
{
internal DrivingSchoolContext context;
internal DbSet<TEntity> dbSet;
public GeneralService(DrivingSchoolContext context)
{
this.context = context;
this.dbSet = context.Set<TEntity>();
}
public virtual IEnumerable<TEntity> Get(
Expression<Func<TEntity, bool>> filter = null,
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
string includeProperties = "")
{
IQueryable<TEntity> query = dbSet;
if (filter != null)
{
query = query.Where(filter);
}
if (includeProperties != null)
{
foreach (var includeProperty in includeProperties.Split
(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
{
query = query.Include(includeProperty);
}
}
if (orderBy != null)
{
return orderBy(query).ToList();
}
else
{
return query.ToList();
}
}
public virtual TEntity GetById(object id)
{
return dbSet.Find(id);
}
public virtual void Insert(TEntity entity)
{
dbSet.Add(entity);
}
public virtual void Delete(object id)
{
TEntity entityToDelete = dbSet.Find(id);
Delete(entityToDelete);
}
public virtual void Delete(TEntity entityToDelete)
{
if (context.Entry(entityToDelete).State == EntityState.Detached)
{
dbSet.Attach(entityToDelete);
}
dbSet.Remove(entityToDelete);
}
public virtual void Update(TEntity entityToUpdate)
{
dbSet.Attach(entityToUpdate);
context.Entry(entityToUpdate).State = EntityState.Modified;
}
}
And my Startup.cs
services.AddScoped(typeof(IGeneralService<>), typeof(GeneralService<>));
If I want to do a get operation in this simple structure, I do this (In my controller)
[HttpGet]
public Student GetStudent(int id)
{
var student = _generalService.Get(filter: x => x.id == id).FirstOrDefault();
return student;
}
I want to place another service layer in front of the controller
when I want to make a insert, it must first comply with my business rules (like phone number , null check etc.) but I couldn't find how to call multiple service (logic) in the "repository pattern" (without creating a new instance)
if i create a new instance like this:
public static DrivingSchoolContext DrivingSchoolContext;
private readonly IGeneralService<Student> _generalService;
private readonly StudentService _studentService;
public StudentController(DrivingSchoolContext drivingSchoolContext, IGeneralService<Student> generalService)
{
DrivingSchoolContext = drivingSchoolContext;
_generalService = generalService;
this._studentService = new StudentService(drivingSchoolContext);
}
[HttpGet]
public Student GetStudent(int id)
{
var studentFromNewInstance = _studentService.GetStudent(id);
var student = _generalService.Get(filter: x => x.id == id).FirstOrDefault();
return student;
}
that code is working but I have too much services and I don't want to create everythem.
Can I refer to my business rules without creating a new "instance" for each service?
I want to use both of my services as follows. For ex we have a student creation scenario. First of all, I want to go to the StudentService
service and apply my business rules. if it passes business rules, I want it to run the Insert method in Generalservice
. Basically like this:
[HttpGet]
public IActionResult CreateStudent(Student student)
{
student.FullName = StudentService.GetFullName(student.firstName + student.lastName);
_generalService.Insert(student);
return Ok("Successfully Created Student");
}
See Question&Answers more detail:os