public Expression ExtractPolicy(Expression expression) { _isNoTracking = false; IsSequenceType = false; ElementType = expression.Type; CachingPolicy = null; if (expression.Type.IsSequenceType(out var elementType)) { IsSequenceType = true; ElementType = elementType; } expression = Visit(expression); if (!_isNoTracking && typeof(BaseEntity).IsAssignableFrom(ElementType)) { // We never gonna cache trackable entities CachingPolicy = null; } else { CachingPolicy = SanitizePolicy(CachingPolicy); } return(expression); }
public void TestDefaultImpl() { var plc = new DbCachingPolicy(); Assert.IsTrue(plc.CanBeCached(null)); Assert.IsTrue(plc.CanBeCached(null, 0)); Assert.AreEqual(TimeSpan.MaxValue, plc.GetExpirationTimeout(null)); Assert.AreEqual(DbCachingMode.ReadWrite, plc.GetCachingMode(null)); }
private DbCachingPolicy SanitizePolicy(DbCachingPolicy policy) { if (policy?.NoCaching == true) { // Caching disabled on query level return(null); } // Try resolve global policy var policyAttribute = GetAllEntityInfos().Get(ElementType)?.Policy; if (policyAttribute != null) { if (policyAttribute.NeverCache) { return(null); } // Either create new policy from attribute or merge attribute with query policy. policy = (policy ?? new DbCachingPolicy()).Merge(policyAttribute); } if (policy != null) { // Global fallbacks from extension options if (policy.ExpirationTimeout == null) { policy.ExpirationTimeout = _extension.DefaultExpirationTimeout; } if (policy.MaxRows == null) { policy.MaxRows = _extension.DefaultMaxRows; } } return(policy); }
protected override Expression VisitMethodCall(MethodCallExpression node) { if (node.Method.IsGenericMethod) { var methodDef = node.Method.GetGenericMethodDefinition(); // Find cachable query extension calls if (methodDef == CachingQueryExtensions.AsCachingMethodInfo) { // Get parameter with "last one wins" CachingPolicy = node.Arguments .OfType <ConstantExpression>() .Where(a => a.Value is DbCachingPolicy) .Select(a => (DbCachingPolicy)a.Value) .Last(); // Cut out extension expression return(Visit(node.Arguments[0])); } else if (!_isNoTracking && (methodDef == CachingQueryExtensions.AsNoTrackingMethodInfo || methodDef == CachingQueryExtensions.AsNoTrackingWithIdentityResolutionMethodInfo)) { // If _isNoTracking is true, we found the marker already. Useless to do it again. if (node.Arguments.Count > 0) { var nodeType = node.Arguments[0]?.Type; if (nodeType != null) { var nodeResultType = nodeType.GetGenericArguments()[0]; _isNoTracking = nodeResultType == ElementType; } } } } return(base.VisitMethodCall(node)); }