У меня есть общий сервис, который определяется следующим образом:
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);
}
который реализован в GenericService.cs
. Это работает очень хорошо, даже с дочерними классами, например. "MyService.cs". В настоящее время я очищаю код и обнаружил одну проблему, которая меня не устраивает.
Если MyService
с типом шаблона MyClass
имеет отношение к MyOtherClass
и я хочу использовать свой общий метод Get-Method, я не получаю объект MyOtherClass
. Поэтому мне нужно создать новый Get-Method в MyService
с соответствующим include, который выглядит примерно так:
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;
}
}
Это не проблема сама по себе, но я начал выяснять способ общей загрузки включений для всех дочерних классов. Это означает, что у меня есть только одна реализация Get-Method, а не отдельная реализация почти для всех моих сервисов.
Моя идея заключалась в том, что в GenericService
я добавляю абстрактный метод:
protected abstract IEnumerable<string> GetIncludes();
который затем вызывается в Get-методе 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;
}
}
Затем в моих дочерних классах я просто реализую абстрактный метод следующим образом:
protected override IEnumerable<string> GetIncludes()
{
return new List<string>() { "MyOtherClass" };
}
Проблема в том, что этот подход не работает. Если я отлаживаю Get-Method моего GenericService, я получаю правильный список включений, и цикл for выполняется правильно, но MyOtherClass всегда имеет значение null. (Очевидно, что это работает, когда я переопределяю метод Get и напрямую пишу this.Context.Set<MyClass>().Include(c => c.MyOtherClass)
)
Вы забыли назначить измененный запрос:
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;
}
}
Мне просто пришлось изменить оператор возврата на: return await query.Where(m => m.Id == id).FirstOrDefaultAsync();
, потому что FindAsync
в этом случае не работает.
Я понимаю! Без
AsQueryable()
не работает все вместе. Сделав его доступным для запросов и назначив измененный запрос, он работает. Спасибо!