private async Task <IList <TodoItemInfo> > InternalGetByQueryAsync(TodoItemQuery todoItemQuery) { logger.LogInformation("About to fetch items using query {@TodoItemQuery} ...", todoItemQuery); IQueryable <TodoItem> todoItems = FilterItems(todoItemQuery) // Read more about query tags here: // https://docs.microsoft.com/en-us/ef/core/querying/tags .TagWith($"{nameof(TodoItemService)}#{nameof(GetByQueryAsync)}") // Read more about no tracking queries here: // https://docs.microsoft.com/en-us/ef/core/querying/tracking#no-tracking-queries .AsNoTracking(); todoItems = SortItems(todoItems, todoItemQuery); todoItems = PaginateItems(todoItems, todoItemQuery); IQueryable <TodoItemInfo> todoItemInfos = ProjectItems(todoItems); IList <TodoItemInfo> result = await todoItemInfos.ToListAsync(); logger.LogInformation("Fetched {TodoItemInfoListCount} todo item(s)", result.Count); if (logger.IsEnabled(LogLevel.Debug)) { logger.LogDebug("{@TodoItemInfoList}", result); } return(result); }
public async Task GetByQueryAsync_UsingValidQuery_MustSucceed(TodoItemQuery todoItemQuery) { // Arrange var inMemoryDatabase = new DbContextOptionsBuilder <TodoDbContext>() .UseInMemoryDatabase($"db--{Guid.NewGuid():N}") .EnableDetailedErrors() .EnableSensitiveDataLogging(); var mockLogger = new Mock <ILogger <TodoItemService> >(); var owner = new Mock <IPrincipal>(); owner.SetupGet(x => x.Identity).Returns(new GenericIdentity("test")); todoItemQuery.Owner = owner.Object; var todoItemService = new TodoItemService(new TodoDbContext(inMemoryDatabase.Options), mockLogger.Object); // Act Func <Task <IList <TodoItemInfo> > > getByQueryAsyncCall = async() => await todoItemService.GetByQueryAsync(todoItemQuery); // Assert await getByQueryAsyncCall.Should().NotThrowAsync("query is valid"); }
public async Task GetByQueryAsync_UsingNullAsQuery_MustThrowException() { // Arrange var mockTodoDbContext = new DbContextMock <TodoDbContext>(DummyOptions); var mockLogger = new Mock <ILogger <TodoItemService> >(); var todoItemService = new TodoItemService(mockTodoDbContext.Object, mockLogger.Object); TodoItemQuery todoItemQuery = null; // Act // ReSharper disable once ExpressionIsAlwaysNull Func <Task <IList <TodoItemInfo> > > getByQueryAsyncCall = async() => await todoItemService.GetByQueryAsync(todoItemQuery); // Assert await getByQueryAsyncCall.Should().ThrowExactlyAsync <ArgumentNullException>( "service cannot fetch data using a null query"); }
private IQueryable <TodoItem> FilterItems(TodoItemQuery todoItemQuery) { IQueryable <TodoItem> todoItems = todoDbContext.TodoItems.Where(todoItem => todoItem.CreatedBy == todoItemQuery.Owner.GetName()); if (todoItemQuery.Id.HasValue) { todoItems = todoItems.Where(todoItem => todoItem.Id == todoItemQuery.Id.Value); } if (!string.IsNullOrWhiteSpace(todoItemQuery.NamePattern)) { todoItems = todoItems.Where(todoItem => EF.Functions.Like(todoItem.Name, todoItemQuery.NamePattern)); } if (todoItemQuery.IsComplete.HasValue) { todoItems = todoItems.Where(todoItem => todoItem.IsComplete == todoItemQuery.IsComplete.Value); } return(todoItems); }
public Task <IList <TodoItemInfo> > GetByQueryAsync(TodoItemQuery todoItemQuery) { Validator.ValidateObject(todoItemQuery, new ValidationContext(todoItemQuery), validateAllProperties: true); return(InternalGetByQueryAsync(todoItemQuery)); }
private static IQueryable <TodoItem> PaginateItems(IQueryable <TodoItem> todoItems, TodoItemQuery todoItemQuery) { int pageIndex = todoItemQuery.PageIndex ?? TodoItemQuery.DefaultPageIndex; int pageSize = todoItemQuery.PageSize ?? TodoItemQuery.DefaultPageSize; IQueryable <TodoItem> result = todoItems.Skip(pageIndex * pageSize).Take(pageSize); return(result); }
private static IQueryable <TodoItem> SortItems(IQueryable <TodoItem> todoItems, TodoItemQuery todoItemQuery) { Expression <Func <TodoItem, object> > keySelector = GetKeySelectorBy(todoItemQuery.SortBy); if (todoItemQuery.IsSortAscending.HasValue && !todoItemQuery.IsSortAscending.Value) { todoItems = todoItems.OrderByDescending(keySelector); } else { todoItems = todoItems.OrderBy(keySelector); } return(todoItems); }