public void ShouldDisplayCorrect_CurrentIncludePath_WhenRemovingNavigation() { var context = new EagerLoadContext(Mock.Of <DbContext>(), Mock.Of <IIncludeStrategy>()); var bookNavigationMock = new Mock <INavigation>(); bookNavigationMock.Setup(nav => nav.Name).Returns(nameof(Book)); var authorNavigationMock = new Mock <INavigation>(); authorNavigationMock.Setup(nav => nav.Name).Returns(nameof(Author)); var publisherNavigationMock = new Mock <INavigation>(); publisherNavigationMock.Setup(nav => nav.Name).Returns(nameof(Publisher)); context.SetCurrentNavigation(bookNavigationMock.Object); context.SetCurrentNavigation(authorNavigationMock.Object); context.SetCurrentNavigation(publisherNavigationMock.Object); Assert.Equal($"{nameof(Book)}.{nameof(Author)}.{nameof(Publisher)}", context.CurrentIncludePath); context.RemoveCurrentNavigation(); Assert.Equal($"{nameof(Book)}.{nameof(Author)}", context.CurrentIncludePath); context.RemoveCurrentNavigation(); Assert.Equal($"{nameof(Book)}", context.CurrentIncludePath); context.RemoveCurrentNavigation(); Assert.Equal(string.Empty, context.CurrentIncludePath); context.RemoveCurrentNavigation(); Assert.Equal(string.Empty, context.CurrentIncludePath); }
public void WhenUsingCachedResult_TheCacheShouldBeSetAndUsedOnFurtherCalls() { var expectedIncludes = new List <string>() { "Test", "Cache" }; var includeFinderMock = new Mock <IncludeFinder>(); includeFinderMock.Setup(finder => finder.BuildIncludePathsForRootType(It.IsAny <EagerLoadContext>())) .Returns(expectedIncludes); var queryIncluderMock = new Mock <QueryIncluder>(); var engine = new IncludeEngine(includeFinderMock.Object, queryIncluderMock.Object); var query = new Book[0].AsQueryable(); var context = new EagerLoadContext(Mock.Of <DbContext>(), Mock.Of <IIncludeStrategy>()); engine.RunIncludesForType(query, context); engine.RunIncludesForType(query, context); Assert.Single(IncludeEngine.CachedIncludePaths); includeFinderMock.Verify(finder => finder.BuildIncludePathsForRootType(It.IsAny <EagerLoadContext>()), Times.Once); }
public void ShouldNotEagerLoad_WhenNavigationIsNotAllowedOnTheRootEntity() { var attribute = new EagerLoadAttribute(notOnRoot: true); var navigationHelperMock = new Mock <NavigationHelper>(); navigationHelperMock.Setup(helper => helper.GetTypeForNavigation(It.IsAny <INavigation>())) .Returns(typeof(Book)); var strategy = new EagerLoadAttributeIncludeStrategy(navigationHelperMock.Object); var context = new EagerLoadContext(Mock.Of <DbContext>(), strategy); var firstNavigationMock = SetupGenericNavigationMock(); EagerLoadAttributeIncludeStrategy.EagerLoadAttributeCache.TryAdd(firstNavigationMock.Object, attribute); context.SetCurrentNavigation(firstNavigationMock.Object); Assert.False(strategy.ShouldIncludeCurrentNavigation(context)); var secondNavigationMock = SetupGenericNavigationMock(); EagerLoadAttributeIncludeStrategy.EagerLoadAttributeCache.TryAdd(secondNavigationMock.Object, new EagerLoadAttribute()); context.SetCurrentNavigation(secondNavigationMock.Object); context.SetCurrentNavigation(firstNavigationMock.Object); Assert.True(strategy.ShouldIncludeCurrentNavigation(context)); }
public void WhenUsingReadOnlyCachedResult_TheCacheShouldBeNotBeSet() { var expectedIncludes = new List <string>() { "Test", "Cache" }; var includeFinderMock = new Mock <IncludeFinder>(); includeFinderMock.Setup(finder => finder.BuildIncludePathsForRootType(It.IsAny <EagerLoadContext>())) .Returns(expectedIncludes); var queryIncluderMock = new Mock <QueryIncluder>(); var engine = new IncludeEngine(includeFinderMock.Object, queryIncluderMock.Object); var query = new Book[0].AsQueryable(); var context = new EagerLoadContext(Mock.Of <DbContext>(), Mock.Of <IIncludeStrategy>(), includeExecution: IncludeExecution.ReadOnlyCache); engine.RunIncludesForType(query, context); Assert.Empty(IncludeEngine.CachedIncludePaths); Assert.Equal(expectedIncludes, context.IncludePathsToInclude); }
public static IQueryable <TEntity> EagerLoadWithStrategy <TEntity>(this IQueryable <TEntity> query, DbContext dbContext, IIncludeStrategy includeStrategy, IncludeExecution includeExecution, params string[] navigationPropertiesToIgnore) where TEntity : class { var context = new EagerLoadContext(dbContext, includeStrategy, navigationPropertiesToIgnore, includeExecution, typeof(TEntity)); return(query.EagerLoadWithContext(context)); }
public void ExecuteBeforeInclude_WillLogTheIncludePaths_IfaLoggerCanBeObtained() { var context = new EagerLoadContext(Mock.Of <DbContext>(), Mock.Of <IIncludeStrategy>(), rootType: typeof(IncludeStrategyTests)); PathsFound.ForEach(i => context.IncludePathsToInclude.Add(i)); var strategyMock = new Mock <IncludeStrategy>(); strategyMock.Setup(s => s.ExecuteBeforeInclude(context)).CallBase(); var strategy = strategyMock.Object; var loggerMock = new Mock <ILogger>(); var serviceProviderMock = new Mock <IServiceProvider>(); serviceProviderMock.Setup(sp => sp.GetService(typeof(ILogger <IncludeStrategy>))).Returns(null); serviceProviderMock.Setup(sp => sp.GetService(typeof(ILogger))).Returns(loggerMock.Object); context.ServiceProvider = serviceProviderMock.Object; strategy.ExecuteBeforeInclude(context); serviceProviderMock.VerifyAll(); //loggerMock.Verify(log => log.Log(It.IsAny<LogLevel>(), It.IsAny<EventId>(), It.IsAny<FormattedLogValues>(), // It.IsAny<Exception>(), It.IsAny<Func<string, Exception, string>>())); }
public void WhenUsingReCachedResult_TheCacheShouldBeReSet() { var expectedIncludes = new List <string>() { "Test", "Cache" }; var notExpectedIncludes = new List <string>() { "Test" }; IncludeEngine.CachedIncludePaths.TryAdd(typeof(Book), notExpectedIncludes); var includeFinderMock = new Mock <IncludeFinder>(); includeFinderMock.Setup(finder => finder.BuildIncludePathsForRootType(It.IsAny <EagerLoadContext>())) .Returns(expectedIncludes); var queryIncluderMock = new Mock <QueryIncluder>(); var engine = new IncludeEngine(includeFinderMock.Object, queryIncluderMock.Object); var query = new Book[0].AsQueryable(); var context = new EagerLoadContext(Mock.Of <DbContext>(), Mock.Of <IIncludeStrategy>(), includeExecution: IncludeExecution.Recache); engine.RunIncludesForType(query, context); Assert.Equal(expectedIncludes, context.IncludePathsToInclude); var cachedIncludes = IncludeEngine.CachedIncludePaths.GetOrAdd(typeof(Book), t => null); Assert.Equal(expectedIncludes, cachedIncludes); includeFinderMock.Verify(finder => finder.BuildIncludePathsForRootType(It.IsAny <EagerLoadContext>()), Times.Once); }
private static EagerLoadAttribute GetAttributeForNavigation(EagerLoadContext context) { var attribute = EagerLoadAttributeCache.GetOrAdd(context.CurrentNavigation, nav => Attribute.GetCustomAttributes(nav.PropertyInfo, typeof(EagerLoadAttribute)) .OfType <EagerLoadAttribute>().FirstOrDefault()); return(attribute); }
internal INavigation[] GetNavigationsForType(EagerLoadContext context, Type type) { return(CachedTypeNavigations.ContainsKey(type) ? CachedTypeNavigations[type] : CachedTypeNavigations.GetOrAdd(type, GetNavigationsForType)); INavigation[] GetNavigationsForType(Type typeToFind) { return(context.DbContext.Model.FindEntityType(typeToFind).GetNavigations().ToArray()); } }
public void ShouldNotEagerLoad_WhenAttributeDoesNotExistOnNavigation() { var strategy = new EagerLoadAttributeIncludeStrategy(); var context = new EagerLoadContext(Mock.Of <DbContext>(), strategy); var navigationMock = SetupGenericNavigationMock(); context.SetCurrentNavigation(navigationMock.Object); Assert.False(strategy.ShouldIncludeCurrentNavigation(context)); }
public void ShouldEagerLoad_ForAllOffRoot() { var strategy = new AllNavigationsIncludeStrategy(); var context = new EagerLoadContext(new Mock <DbContext>().Object, strategy); var navigationMock = new Mock <INavigation>(); navigationMock.Setup(nav => nav.Name).Returns(nameof(Book)); context.SetCurrentNavigation(navigationMock.Object); Assert.True(strategy.ShouldIncludeCurrentNavigation(context)); }
public void GlobalSetup() { _testDbContext = new TestDbContext(new DbContextOptionsBuilder <TestDbContext>() .UseInMemoryDatabase(Guid.NewGuid().ToString()).Options); _strategy = new EagerLoadAttributeIncludeStrategy(); _context = new EagerLoadContext(_testDbContext, _strategy, new string[0], IncludeExecution.NoCache, typeof(Book)); _includeFinder = new Engine.IncludeFinder(); }
public void ShouldNotEagerLoad_WhenNavigationIsNotValid() { var strategy = new EagerLoadAttributeIncludeStrategy(); var context = new EagerLoadContext(Mock.Of <DbContext>(), strategy); var navigationMock = new Mock <INavigation>(); navigationMock.Setup(nav => nav.Name).Returns(nameof(Book)); context.SetCurrentNavigation(navigationMock.Object); Assert.False(strategy.ShouldIncludeCurrentNavigation(context)); }
public void ShouldDoNothing_WhenNavigationAddedIsNull() { var context = new EagerLoadContext(Mock.Of <DbContext>(), Mock.Of <IIncludeStrategy>()); Assert.Equal(string.Empty, context.CurrentIncludePath); Assert.Null(context.CurrentNavigation); context.SetCurrentNavigation(null); Assert.Equal(string.Empty, context.CurrentIncludePath); Assert.Null(context.CurrentNavigation); }
public void ShouldDisplayCorrect_CurrentIncludePath_WhenAddingFirstNavigation() { var context = new EagerLoadContext(Mock.Of <DbContext>(), Mock.Of <IIncludeStrategy>()); var navigationMock = new Mock <INavigation>(); navigationMock.Setup(nav => nav.Name).Returns(nameof(Book)); context.SetCurrentNavigation(navigationMock.Object); Assert.Equal(nameof(Book), context.CurrentIncludePath); }
public void ShouldReturnTheCorrectNavigations_ForMappedTypes() { var context = new EagerLoadContext(TestDbContext.Instance, new Mock <IIncludeStrategy>().Object); var expectedNavigations = TestDbContext.Instance.Model.FindEntityType(typeof(Book)).GetNavigations().ToList(); var navigationFinder = new NavigationFinder(); var actualNavigations = navigationFinder.GetNavigationsForType(context, typeof(Book)).ToList(); Assert.Equal(expectedNavigations.Count, actualNavigations.Count); expectedNavigations.ForEach(nav => { Assert.Contains(nav, actualNavigations); }); }
public void ShouldReturnOriginalQuery_IfNoIncludePathsGetFound() { var includeFinderMock = new Mock <IncludeFinder>(); var queryIncluderMock = new Mock <QueryIncluder>(); var engine = new IncludeEngine(includeFinderMock.Object, queryIncluderMock.Object); var query = new Book[0].AsQueryable(); var context = new EagerLoadContext(Mock.Of <DbContext>(), Mock.Of <IIncludeStrategy>()); Assert.Equal(query, engine.RunIncludesForType(query, context)); queryIncluderMock.VerifyNoOtherCalls(); }
public void ShouldSetRootType_IfNoRootTypeOnTheContext() { var includeFinderMock = new Mock <IncludeFinder>(); var queryIncluderMock = new Mock <QueryIncluder>(); var engine = new IncludeEngine(includeFinderMock.Object, queryIncluderMock.Object); var query = new Book[0].AsQueryable(); var context = new EagerLoadContext(Mock.Of <DbContext>(), Mock.Of <IIncludeStrategy>()); engine.RunIncludesForType(query, context); Assert.Equal(typeof(Book), context.RootType); }
public void ShouldNotEagerLoad_IfIncludePathToConsiderShouldBeIgnored() { var strategy = new AllNavigationsIncludeStrategy(); var context = new EagerLoadContext(new Mock <DbContext>().Object, strategy); context.IncludePathsToIgnore.Add(nameof(INavigation)); //context.ParentIncludePath = ""; var navigationMock = new Mock <INavigation>(); navigationMock.Setup(nav => nav.Name).Returns(nameof(INavigation)); context.SetCurrentNavigation(navigationMock.Object); Assert.False(strategy.ShouldIncludeCurrentNavigation(context)); }
public virtual void ExecuteBeforeInclude(EagerLoadContext context) { var loggerInject = context.ServiceProvider?.GetService(typeof(ILogger <IncludeStrategy>)) ?? context.ServiceProvider?.GetService(typeof(ILogger)); if (!(loggerInject is ILogger logger)) { return; } var includePaths = JsonSerializer.Serialize(context.IncludePathsToInclude); logger.LogInformation($"{IncludeLogMessage}{context.RootType.Name}: {includePaths}"); }
public void ShouldNotEagerLoad_WhenAttributeSetToNever() { var strategy = new EagerLoadAttributeIncludeStrategy(); var context = new EagerLoadContext(Mock.Of <DbContext>(), strategy); var navigationMock = SetupGenericNavigationMock(); var navigation = navigationMock.Object; context.SetCurrentNavigation(navigation); var attribute = new EagerLoadAttribute(never: true); EagerLoadAttributeIncludeStrategy.EagerLoadAttributeCache.TryAdd(navigation, attribute); Assert.False(strategy.ShouldIncludeCurrentNavigation(context)); }
public void FilterIncludePathsBeforeInclude_RemovesPathsThatMatchTheExcludeList() { var pathsToFilter = new[] { "Book.Author" }; var context = new EagerLoadContext(Mock.Of <DbContext>(), Mock.Of <IIncludeStrategy>(), pathsToFilter); PathsFound.ForEach(i => context.IncludePathsToInclude.Add(i)); var strategyMock = new Mock <IncludeStrategy>(); strategyMock.Setup(s => s.FilterIncludePathsBeforeInclude(context)).CallBase(); var strategy = strategyMock.Object; strategy.FilterIncludePathsBeforeInclude(context); Assert.Equal(6, context.IncludePathsToInclude.Count); }
public static async Task Run() { var serviceProvider = await SetupServices(); var testRunner = serviceProvider.GetRequiredService <TestRunner>(); EagerLoadContext.InitializeServiceProvider(serviceProvider); await testRunner.RunTest1(); //await testRunner.RunTest2(); //await testRunner.RunTest3(); //await testRunner.RunTest4(); //await testRunner.RunTest5(); //await testRunner.RunTest6(); }
public void ShouldReturnOriginalQuery_WithNoExecution_WhenIncludeExecutionIsSkip() { var includeFinderMock = new Mock <IncludeFinder>(); var queryIncluderMock = new Mock <QueryIncluder>(); var engine = new IncludeEngine(includeFinderMock.Object, queryIncluderMock.Object); var query = new Book[0].AsQueryable(); var context = new EagerLoadContext(Mock.Of <DbContext>(), Mock.Of <IIncludeStrategy>(), includeExecution: IncludeExecution.Skip); Assert.Equal(query, engine.RunIncludesForType(query, context)); includeFinderMock.VerifyNoOtherCalls(); queryIncluderMock.VerifyNoOtherCalls(); }
public void ShouldEagerLoad_WhenAttributeExist() { var strategy = new AttributeExistsIncludeStrategy <EagerLoadAttribute>(); var context = new EagerLoadContext(new Mock <DbContext>().Object, strategy); var navigationMock = new Mock <INavigation>(); navigationMock.Setup(nav => nav.Name).Returns(nameof(Book)); context.SetCurrentNavigation(navigationMock.Object); navigationMock.Setup(nav => nav.PropertyInfo) .Returns(GetType().GetProperty(nameof(HasEagerLoadAttribute))); Assert.True(strategy.ShouldIncludeCurrentNavigation(context)); navigationMock.Setup(nav => nav.PropertyInfo) .Returns(GetType().GetProperty(nameof(HasManyIncludingEagerLoadAttribute))); Assert.True(strategy.ShouldIncludeCurrentNavigation(context)); }
public void ShouldUseSuppliedPathPredicate_ToTestIfTheNavigationShouldBeIncluded() { var pathChecked = string.Empty; var strategy = new PredicateIncludeStrategy(path => { pathChecked = path; return(true); }); var context = new EagerLoadContext(Mock.Of <DbContext>(), strategy); var navigationMock = new Mock <INavigation>(); navigationMock.Setup(nav => nav.Name).Returns(nameof(Book)); context.SetCurrentNavigation(navigationMock.Object); Assert.True(strategy.ShouldIncludeCurrentNavigation(context)); Assert.Equal(nameof(Book), pathChecked); }
private void SetupPreFilteredIncludePaths(EagerLoadContext context) { switch (context.IncludeExecution) { case IncludeExecution.Cached: { context.IncludePathsToInclude = CachedIncludePaths.GetOrAdd(context.RootType, (type) => _includeFinder.BuildIncludePathsForRootType(context)?.ToList() ?? new List <string>(0)); break; } case IncludeExecution.ReadOnlyCache: { context.IncludePathsToInclude = CachedIncludePaths.ContainsKey(context.RootType) ? CachedIncludePaths.GetValueOrDefault(context.RootType) : _includeFinder.BuildIncludePathsForRootType(context); break; } case IncludeExecution.NoCache: { context.IncludePathsToInclude = _includeFinder.BuildIncludePathsForRootType(context); break; } case IncludeExecution.Recache: { context.IncludePathsToInclude = _includeFinder.BuildIncludePathsForRootType(context); CachedIncludePaths.AddOrUpdate(context.RootType, (t) => context.IncludePathsToInclude?.ToList() ?? new List <string>(0), (t, l) => context.IncludePathsToInclude?.ToList() ?? new List <string>(0)); break; } default: throw new ArgumentOutOfRangeException(); } context.IncludePathsToInclude = (context.IncludePathsToInclude == null) ? new List <string>(0) : new List <string>(context.IncludePathsToInclude); }
public virtual void FilterIncludePathsBeforeInclude(EagerLoadContext context) { //var foreach (var pathToExclude in context.IncludePathsToIgnore) { for (var i = context.IncludePathsToInclude.Count - 1; i >= 0; i--) { if (context.IncludePathsToInclude[i].StartsWith(pathToExclude, StringComparison.InvariantCultureIgnoreCase)) { context.IncludePathsToInclude.Remove(context.IncludePathsToInclude[i]); } } } //foreach (var navigationPath in context.IncludePathsToInclude.ToArray()) //{ // if (context.IncludePathsToIgnore.Any(nav => navigationPath.StartsWith(nav))) // { // context.IncludePathsToInclude.Remove(navigationPath); // } //} }
private void BuildIncludesForEagerLoadContext(EagerLoadContext context) { BuildIncludesForEagerLoadContext(); void BuildIncludesForEagerLoadContext() { var navigationsToConsider = _navigationFinder.GetNavigationsForType(context, context.CurrentType ?? context.RootType); foreach (var navigation in navigationsToConsider) { context.SetCurrentNavigation(navigation); if (context.IncludeStrategy.ShouldIncludeCurrentNavigation(context)) { context.IncludePathsToInclude.Add(context.CurrentIncludePath); BuildIncludesForEagerLoadContext(); } context.RemoveCurrentNavigation(); } } }
public void ShouldSetFinderResults_IntoTheContext() { var expectedIncludes = new List <string>() { "Test", "Cache" }; var includeFinderMock = new Mock <IncludeFinder>(); includeFinderMock.Setup(finder => finder.BuildIncludePathsForRootType(It.IsAny <EagerLoadContext>())) .Returns(expectedIncludes); var queryIncluderMock = new Mock <QueryIncluder>(); var engine = new IncludeEngine(includeFinderMock.Object, queryIncluderMock.Object); var query = new Book[0].AsQueryable(); var context = new EagerLoadContext(Mock.Of <DbContext>(), Mock.Of <IIncludeStrategy>()); engine.RunIncludesForType(query, context); Assert.Equal(expectedIncludes, context.IncludePathsToInclude); }