'EntityFramework Generic Service with Generic Includes
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))
Solution 1:[1]
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;
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
