EntityFramework 具有通用包含的通用服务

EntityFramework Generic Service with Generic Includes

我有一个通用服务,定义如下:

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中实现。这工作得很好,即使使用 child 类,例如“MyService.cs”。我目前正在清理代码,我发现了一个问题,我对此并不满意。

如果模板类型 MyClassMyServiceMyOtherClass 有关系并且我想使用我的通用 Get-Method,我没有收到 object 共 MyOtherClass。因此,我需要使用相应的包含在 MyService 中创建一个新的 Get-Method,它看起来像这样:

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;
    }
}

这本身不是问题,但我开始想出一种方法来为所有 child 类 一般加载包含。这意味着,我只有 Get-Method 的一个实现,几乎所有服务都没有一个单独的实现。

我的想法是,在 GenericService 中,我添加了一个抽象方法:

protected abstract IEnumerable<string> GetIncludes();

然后在 GenericService 的 Get-Method 中调用:

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;
    }
}

在我的 child 类 中,我简单地实现了这样的抽象方法:

protected override IEnumerable<string> GetIncludes()
{
    return new List<string>() { "MyOtherClass" };
}

问题是,这种方法似乎行不通。如果我调试我的 GenericService 的 Get-Method,我得到正确的包含列表并且 for-loop 被正确执行,但 MyOtherClass 始终为空。 (显然有效,当我重写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;
    }
}