隔离.ToListAsync()的最佳方法是什么



我有一个Blazor应用程序,它使用EntityFrameworkCore和Generic存储库。

在我的服务中,我查询存储库,但当我尝试调用.ToListAsync((时;-它要求我添加-使用Microsoft.EntityFrameworkCore;这意味着它将创建对EF的依赖关系。我不想把我的服务绑定到EF。

.ToListAsync((是一个扩展方法。将服务与其隔离的最佳方式是什么?我通过一个额外的包装类AsyncConverter实现了它。有更好的方法吗?

public class AsyncConverter : IAsyncConverter
{
public Task<List<TSource>> ConvertToListAsync<TSource>(IQueryable<TSource> source, CancellationToken cancellationToken = default)
{
return source.ToListAsync(cancellationToken);
}
}
public class EfRepository<TEntity> : IRepository<TEntity>
where TEntity : class
{
public EfRepository(ApplicationDbContext context)
{
this.Context = context ?? throw new ArgumentNullException(nameof(context));
this.DbSet = this.Context.Set<TEntity>();
}
protected DbSet<TEntity> DbSet { get; set; }
protected ApplicationDbContext Context { get; set; }
public virtual IQueryable<TEntity> All() => this.DbSet;
}


public class ItemsDataService : IItemsDataService
{
private readonly IRepository<Item> _itemsRepository;
private readonly IMapper _mapper;
private readonly IAsyncConverter _asyncConverter;
private readonly IStringLocalizer<Errors> _localizer;

public ItemsDataService(IRepository<Item> itemsRepository, 
IMapper mapper,
IAsyncConverter asyncConverter,
IStringLocalizer<Errors> localizer = null)
{
_itemsRepository = itemsRepository;
_mapper = mapper;
_asyncConverter = asyncConverter;
_localizer = localizer;
}
public async Task<Response<IEnumerable<ItemNameDto>>> GetItemsNamesAsync(string searchWord, string userId)
{
try
{
searchWord.ThrowIfNull();
userId.ThrowIfNullOrEmpty();
var query = _itemsRepository.All()
.Where(x => x.UserId == userId);
var names = new List<ItemNameDto>();
if (!string.IsNullOrEmpty(searchWord))
{
query = query.Where(x => x.Name.ToLower().Contains(searchWord.ToLower()));
}
var queryProjection = _mapper.ProjectTo<ItemNameDto>(query); **/*.ToListAsync(); - This would add a dependency to EntityFrameworkCore. That it why I introduced AsyncConverter*/**
names = await _asyncConverter.ConvertToListAsync(queryProjection);
var response = ResponseBuilder.Success<IEnumerable<ItemNameDto>>(names);
return response;
}
catch (Exception ex)
{
var response = ResponseBuilder.Failure<IEnumerable<ItemNameDto>>("An error occured while getting items names.");
return response;
}
}

我通常的方法是将所有的查询构建代码放在我的存储库中,并让它们返回一个具体化的结果。因此,在单元测试我的服务类时,我可以模拟存储库层。

尝试对数据访问层进行单元测试可能会很麻烦,因为它本质上是设计为集成层的。使用内存中对象时以一种方式工作的查询在实体框架转换时可能会有不同的行为。

如果您更喜欢在服务层中构建查询,Ian Kemp的方法可以工作,基本上将ConvertToListAsync方法放入EfRepository类及其接口中,而不是注入一个全新的服务。

相关内容

最新更新