I have a generic service, which is defined like this:
public interface IGenericService<T> : IDisposable
where T : class, IModel
{
Task<bool> Add(T entity);
Task<bool> AddOrUpdate(T entity);
Task<bool> Update(T entity);
Task<T?> Get(int id);
Task<bool> Exists(int id);
Task<IEnumerable<T>> GetAll();
Task<bool> Delete(T entity);
Task<IEnumerable<T>> GetAll(int numberOfElements, int page);
Task<int> NumberOfEntries();
Task<T?> Refresh(T entity);
}
which is implemented in GenericService.cs
. This works pretty well, even with child classes, e.g. "MyService.cs". I am currently cleaning up the code and I found one issue, I am not happy with.
If MyService
with the template type MyClass
has a relationship to MyOtherClass
and I want to use my generic Get-Method, I do not receive the object of MyOtherClass
. Therefore, I need to create a new Get-Method in MyService
with the corresponding include, which looks something like this:
public new async Task<MyClass?> Get(int id)
{
try
{
return await this.Context.Set<MyClass>().Include(c => c.MyOtherClass).FirstOrDefaultAsync(d => d.Id == id);
}
catch (Exception)
{
return null;
}
}
This is not a problem per se, but I started to figure out a way to generically load the includes for all the child classes. This means, that I only have one implementation of the Get-Method and not a separate one for nearly all of my services.
My idea was, that in GenericService
, I add an abstract method:
protected abstract IEnumerable<string> GetIncludes();
which is then called in the Get-Method of the GenericService:
public async Task<TModel?> Get(int id)
{
try
{
var query = this.Context.Set<TModel>();
foreach (var include in this.GetIncludes())
{
query.Include(include);
}
return await query.FindAsync(id);
}
catch (Exception)
{
return null;
}
}
In my child classes I then simply implement the abstract method like this:
protected override IEnumerable<string> GetIncludes()
{
return new List<string>() { "MyOtherClass" };
}
The problem is, that this approach does not seem to work. If I debug the Get-Method of my GenericService, I get the correct List of Includes and the for-loop is executed correctly, but MyOtherClass is always null. (It obviously works, when I override the Get Method and directly write this.Context.Set<MyClass>().Include(c => c.MyOtherClass)
)
CodePudding user response:
You have forgotten to assign modified query:
query = query.Include(include);
public async Task<TModel?> Get(int id)
{
try
{
var query = this.Context.Set<TModel>().AsQueryable();
foreach (var include in this.GetIncludes())
{
query = query.Include(include);
}
return await query.FirstOrDefaultAsync(m => m.Id == id);
}
catch (Exception)
{
return null;
}
}