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”。我目前正在清理代码,我发现了一个问题,我对此并不满意。
如果模板类型 MyClass
的 MyService
与 MyOtherClass
有关系并且我想使用我的通用 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;
}
}
我有一个通用服务,定义如下:
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”。我目前正在清理代码,我发现了一个问题,我对此并不满意。
如果模板类型 MyClass
的 MyService
与 MyOtherClass
有关系并且我想使用我的通用 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;
}
}