public void GivenSerializeWhenCalledWithNullExpressionThenShouldThrowArgumentNull()
        {
            Expression expression = null;

            Assert.Throws <ArgumentNullException>(() =>
                                                  QueryExprSerializer.Serialize(expression));
        }
        public void MultipleSelectManyProjectionWorks()
        {
            var dataQuery = TestableThing.MakeQuery(5);

            IQueryable <Tuple <string, string, string> > SelectMany(IQueryable <TestableThing> query) =>
            query.SelectMany(t => t.ChildThings, (t, c) => new
            {
                parentId = t.Id,
                childId  = c.Id,
                children = c.ChildThings
            }).SelectMany(tc => tc.children, (tc, tcc) => new
            {
                tc.parentId,
                tc.childId,
                grandChildId = tcc.Id
            }).Select(t => Tuple.Create(t.parentId, t.childId, t.grandChildId));

            var query = SelectMany(IQueryableExtensions.CreateQueryTemplate <TestableThing>());

            var root = QueryExprSerializer.Serialize(query);
            var json = wrapper.FromSerializationRoot(root);
            // make sure we're not just pulling from the cache
            var deserializedRoot = wrapper.ToSerializationRoot(json);
            var newQuery         = QueryExprSerializer.DeserializeQuery <Tuple <string, string, string> >(deserializedRoot, dataQuery);

            var expected = SelectMany(dataQuery).ToList();
            var actual   = newQuery.ToList();

            Assert.NotNull(actual);
            Assert.Equal(expected, actual);
        }
        public void GivenSerializeWhenCalledWithNullQueryThenShouldThrowArgumentNull()
        {
            IQueryable query = null;

            Assert.Throws <ArgumentNullException>(() =>
                                                  QueryExprSerializer.Serialize(query));
        }
예제 #4
0
        /// <summary>
        /// Deserializes the query.
        /// </summary>
        /// <param name="template">The <see cref="IQueryable"/> to run.</param>
        /// <param name="json">The stream with json info.</param>
        /// <param name="logger">The logger.</param>
        /// <returns>The <see cref="IQueryable"/> result.</returns>
        public async Task <QueryResult> DeserializeAsync(
            IQueryable template,
            Stream json,
            ILogger logger = null)
        {
            Ensure.NotNull(() => template);
            Ensure.NotNull(() => json);

            var request = await JsonSerializer.DeserializeAsync <SerializationPayload>(json);

            Ensure.VariableNotNull(() => request);
            Ensure.NotNullOrWhitespace(() => request.Json);

            if (logger != null)
            {
                logger.LogInformation($"Query payload: {request.Json}");
            }

            var options = jsonOptions.Value();
            var root    = jsonSerializer.Value.ToSerializationRoot(request.Json, options);
            var query   = QueryExprSerializer.DeserializeQuery(template, root);

            if (logger != null)
            {
                logger.LogInformation($"Deserialized query: {query.Expression}");
            }

            return(new QueryResult
            {
                Query = query,
                QueryType = request.GetQueryType(),
            });
        }
        public void GivenQueryWhenSerializeCalledThenShouldDeserialize(
            IQueryable query,
            Queries type)
        {
            var json = QueryExprSerializer.Serialize(query);

            // make sure we're not just pulling from the cache
            Reset();

            IQueryable queryHost = TestableThing.MakeQuery(10);

            var newQuery = QueryExprSerializer.DeserializeQuery(queryHost, json);

            // can't do equivalency check for anonymous types
            if (!query.AsEnumerableExpression().OfType <NewExpression>()
                .Any(t => t.Type.IsAnonymousType()))
            {
                Assert.True(query.IsEquivalentTo(newQuery));
            }

            if (newQuery is IQueryable <ExpandoObject> anonymousQuery)
            {
                var list = anonymousQuery.ToList();
                Assert.NotNull(list);
            }
            else if (newQuery is IQueryable <TestableThing> thingQuery)
            {
                var list = thingQuery.ToList();
                ValidateQuery(list, type);
            }
        }
 public JsonWrapperTests()
 {
     QueryExprSerializer.ConfigureRules(rules =>
                                        rules.RuleForType <QueryExprSerializerTests>()
                                        .RuleForType <TestableThing>()
                                        .RuleForType(typeof(Tuple)));
 }
 private string queryJson(
     bool isCount    = false,
     bool useProduct = false,
     bool isSingle   = false) => JsonSerializer.Serialize(
     new SerializationPayload(isCount ? PayloadType.Count : (isSingle ? PayloadType.Single : PayloadType.Array))
 {
     Json = jsonWrapper.FromSerializationRoot(
         QueryExprSerializer.Serialize(altQuery ?? (useProduct ? productsQuery : query)))
 });
 private void Reset()
 {
     ServiceHost.GetService <IMemberAdapter>().Reset();
     QueryExprSerializer.ConfigureRules(
         rules => rules.RuleForType <QueryExprSerializerTests>()
         .RuleForType <TestableThing>()
         .RuleForType <BinarySerializerTests>()
         .RuleForType(typeof(KeyValuePair))
         .RuleForType(typeof(Tuple)));
 }
        public void DeserializeWithConfigurationUsesConfiguration()
        {
            var expr         = 42.AsConstantExpression();
            var serialized   = QueryExprSerializer.Serialize(expr);
            var deserialized = QueryExprSerializer.Deserialize(
                serialized,
                null,
                config => config.CompressExpressionTree(false),
                null);

            Assert.NotNull(deserialized);
        }
        public void GivenQueryCanSerializeAndDeserialize(IQueryable query, QueryExprSerializerTests.Queries queryType)
        {
            var root             = QueryExprSerializer.Serialize(query, config => config.CompressExpressionTree(false));
            var json             = wrapper.FromSerializationRoot(root);
            var deserializedRoot = wrapper.ToSerializationRoot(json);

            Assert.NotNull(deserializedRoot);
            IQueryable queryHost         = TestableThing.MakeQuery(10);
            var        deserializedQuery = QueryExprSerializer.DeserializeQuery(queryHost, deserializedRoot);

            Assert.NotNull(deserializedQuery);
            Assert.True(query.Expression.IsEquivalentTo(deserializedQuery.Expression));
        }
        public void GivenQueryWhenSerializeCalledThenShouldDeserializeForType(
            IQueryable <TestableThing> query,
            Queries type)
        {
            var json = QueryExprSerializer.Serialize(query);

            Reset();

            var queryHost = TestableThing.MakeQuery(100);
            var newQuery  = QueryExprSerializer.DeserializeQuery <TestableThing>(json, queryHost);

            Assert.True(query.IsEquivalentTo(newQuery));
            ValidateQuery(newQuery.ToList(), type);
        }
        public void HandlesElementInits()
        {
            Expression <Func <DataHost> > elemInit = () => new DataHost {
                Elems = { new DataElem() }
            };
            var root             = QueryExprSerializer.Serialize(elemInit, config => config.CompressExpressionTree(false));
            var json             = wrapper.FromSerializationRoot(root);
            var deserializedRoot = wrapper.ToSerializationRoot(json);

            QueryExprSerializer.ConfigureRules(rules => rules.RuleForType <DataHost>()
                                               .RuleForType <DataElem>());
            var deserializedExpr = QueryExprSerializer.Deserialize <LambdaExpression>(deserializedRoot);

            Assert.True(elemInit.IsEquivalentTo(deserializedExpr));
        }
        public void HandlesNullAnonymousTypes()
        {
            var expected = new
            {
                Id      = 1,
                SubAnon = default(object)
            };

            var expr             = expected.AsConstantExpression();
            var root             = QueryExprSerializer.Serialize(expr);
            var json             = wrapper.FromSerializationRoot(root);
            var deserializedRoot = wrapper.ToSerializationRoot(json);
            var deserializedExpr = QueryExprSerializer.Deserialize <ConstantExpression>(deserializedRoot);

            Assert.True(expressionEvaluator.Value.AnonymousValuesAreEquivalent(expr.Value, deserializedExpr.Value));
        }
        public void HandlesInterfaces()
        {
            var expr = Expression.Constant(new IdContainer
            {
                Id   = Guid.NewGuid().ToString(),
                Name = nameof(IdContainer),
            }, typeof(IHaveId));
            var root             = QueryExprSerializer.Serialize(expr, config => config.CompressExpressionTree(false));
            var json             = wrapper.FromSerializationRoot(root);
            var deserializedRoot = wrapper.ToSerializationRoot(json);
            var deserializedExpr = QueryExprSerializer.Deserialize <ConstantExpression>(deserializedRoot);

            Assert.Equal(typeof(IHaveId), deserializedExpr.Type);
            Assert.True(deserializedExpr.Value is IdContainer);
            Assert.Equal(nameof(IdContainer), ((IdContainer)deserializedExpr.Value).Name);
        }
        public void GivenRulesPassedWhenMapPowerToolsEFCoreBaseCalledThenShouldConfigureRules()
        {
            IEndpointRouteBuilder builder = null;

            CreateSimpleServer(config => builder = config);

            builder.MapPowerToolsEFCore(
                routePattern,
                defaultTypes,
                rules => rules.RuleForType <MiddlewareExtensionsTests>());

            var engine = ServiceHost.GetService <IRulesEngine>();

            Assert.True(engine.MemberIsAllowed(typeof(MiddlewareExtensionsTests)));

            // reset rules
            QueryExprSerializer.ConfigureRules();
        }
        public void SerializesAndDeserializesAnonymousTypes()
        {
            var expected = new
            {
                Id      = 1,
                SubAnon = new
                {
                    Id  = 2,
                    Two = 2.ToString()
                }
            };

            var expr             = expected.AsConstantExpression();
            var root             = QueryExprSerializer.Serialize(expr);
            var json             = wrapper.FromSerializationRoot(root);
            var deserializedRoot = wrapper.ToSerializationRoot(json);
            var deserializedExpr = QueryExprSerializer.Deserialize <ConstantExpression>(deserializedRoot);

            Assert.True(expressionEvaluator.Value.AnonymousValuesAreEquivalent(expr.Value, deserializedExpr.Value));
        }
        public void NewArrayExpressionShouldDeserialize()
        {
            var newArray = Expression.NewArrayInit(
                typeof(int),
                Expression.Constant(1),
                Expression.Constant(2));

            Func <IConfigurationBuilder, IConfigurationBuilder> config = builder =>
                                                                         builder.CompressTypes(false).CompressExpressionTree(false);
            var expr = QueryExprSerializer.Serialize(newArray, cfg => config(cfg));

            var state = config(ServiceHost.GetService <IConfigurationBuilder>()).Configure();

            var deserialized = serializer.Deserialize(expr.Expression as NewArray, state);

            Assert.Equal(newArray.Type, deserialized.Type);
            Assert.Equal(
                newArray.Expressions.OfType <ConstantExpression>().Select(ce => ce.Value),
                deserialized.Expressions.OfType <ConstantExpression>().Select(ce => ce.Value));
        }
예제 #18
0
        /// <summary>
        /// Entry point.
        /// </summary>
        /// <param name="args">Arguments passed in.</param>
        /// <returns>A <see cref="Task"/> for asychronous processing.</returns>
        public static async Task Main(string[] args)
        {
            var builder = WebAssemblyHostBuilder.CreateDefault(args);

            builder.RootComponents.Add <App>("app");
            builder.Services.AddScoped(sp => new HttpClient {
                BaseAddress = new Uri(builder.HostEnvironment.BaseAddress)
            });

            // this adds the client with the base address to post to /efcore/{context}/{collection}
            builder.Services.AddExpressionPowerToolsEFCore(new Uri(builder.HostEnvironment.BaseAddress));

            if (builder.HostEnvironment.IsDevelopment())
            {
                QueryExprSerializer.ConfigureDefaults(config => config.CompressTypes(false));
            }

            // this adds a helper class for composing the query
            builder.Services.AddScoped(
                sp => new RemoteQueryClientService());

            await builder.Build().RunAsync();
        }
 public BinarySerializerTests()
 {
     QueryExprSerializer.ConfigureRules(config => config.RuleForType <BinarySerializerTests>());
 }
 private string queryJson() => JsonSerializer.Serialize(
     new SerializationPayload
 {
     Json = jsonWrapper.FromSerializationRoot(QueryExprSerializer.Serialize(query))
 });
 public QueryExprSerializerTests()
 {
     QueryExprSerializer.ConfigureDefaults(
         config => config.CompressExpressionTree(false));
 }
        public void AlternateSelectManyWorks()
        {
            QueryExprSerializer.ConfigureRules(
                rules => rules.RuleForType <RelatedThing>());

            var db = typeof(JsonWrapperTests).Assembly.GetTypes()
                     .Select(t => new MockType
            {
                Id      = t.ToString(),
                Name    = t.FullName,
                Methods = t.GetMethods().Select(
                    m => new MockMethod
                {
                    Id         = m.ToString(),
                    Name       = m.Name,
                    Parameters = m.GetParameters()
                                 .Select(p => new MockParameter
                    {
                        Id   = $"{p.Position}-{p.ParameterType}",
                        Name = p.Name,
                    }).ToList()
                }).ToList()
            });

            Func <IQueryable <MockType>, IQueryable <RelatedThing> > makeQuery = q =>
                                                                                 q
                                                                                 .Where(t => t.Name != null)
                                                                                 .SelectMany(
                t =>
                t.Methods, (t, m) =>
                new
            {
                t.Name,
                MethodName = m.Name,
                m.Parameters,
            })
                                                                                 .SelectMany(
                tm => tm.Parameters,
                (tm, p) =>
                new RelatedThing
            {
                TypeName      = tm.Name,
                MethodName    = tm.MethodName,
                ParameterName = p.Name,
            })
                                                                                 .OrderBy(r => r.TypeName)
                                                                                 .ThenBy(r => r.MethodName)
                                                                                 .ThenBy(r => r.ParameterName);

            var queryToSerialize = makeQuery(new List <MockType>().AsQueryable());

            var root = QueryExprSerializer.Serialize(queryToSerialize);
            var json = wrapper.FromSerializationRoot(root);

            var deserializedRoot = wrapper.ToSerializationRoot(json);
            var newQuery         = QueryExprSerializer.DeserializeQuery <RelatedThing>(deserializedRoot, db.AsQueryable());

            var result   = makeQuery(db.AsQueryable());
            var expected = result.ToList();
            var actual   = newQuery.ToList();

            Assert.NotNull(actual);
            Assert.Equal(expected.Count(), actual.Count());
        }
예제 #23
0
 private string GetJson(bool isCount = false) =>
 JsonSerializer.Serialize(
     new SerializationPayload(isCount ? PayloadType.Count : PayloadType.Array)
 {
     Json = jsonWrapper.FromSerializationRoot(QueryExprSerializer.Serialize(query)),
 });
        /// <summary>
        /// Main configuration method for Power Tools EF Core middleware.
        /// </summary>
        /// <param name="endpointRouteBuilder">The <see cref="IEndpointRouteBuilder"/>.</param>
        /// <param name="pattern">The pattern for the route (defaults to <c>/efcore</c>).</param>
        /// <param name="dbContextTypes">The list of <c>DbContext</c> types to support.</param>
        /// <param name="rules">The <see cref="IRulesConfiguration"/> to configure serialization rules.</param>
        /// <param name="noDefaultRules">Determines whether the default rule set should be applied.</param>
        /// <param name="options">The <see cref="IConfigurationBuilder"/> to configure options.</param>
        /// <returns>The <see cref="IEndpointConventionBuilder"/>.</returns>
        public static IEndpointConventionBuilder MapPowerToolsEFCore(
            this IEndpointRouteBuilder endpointRouteBuilder,
            RoutePattern pattern,
            Type[] dbContextTypes,
            Action <IRulesConfiguration> rules = null,
            bool noDefaultRules = false,
            Action <IConfigurationBuilder> options = null)
        {
            Ensure.NotNull(() => endpointRouteBuilder);
            Ensure.NotNull(() => pattern);
            Ensure.NotNull(() => dbContextTypes);

            if (pattern.Parameters.Count != 2)
            {
                throw new ArgumentException(
                          $"{DefaultPattern}<~>{pattern.RawText}",
                          nameof(pattern));
            }

            if (!pattern.Parameters.Any(p => p.Name == Context))
            {
                throw new ArgumentException(Context, nameof(pattern));
            }

            if (!pattern.Parameters.Any(p => p.Name == Collection))
            {
                throw new ArgumentException(Collection, nameof(pattern));
            }

            if (dbContextTypes.Length == 0)
            {
                throw new ArgumentException(
                          $"{nameof(dbContextTypes)}.Length = 0",
                          nameof(dbContextTypes));
            }

            var badType = dbContextTypes.FirstOrDefault(
                t => !typeof(DbContext).IsAssignableFrom(t));

            if (badType != null)
            {
                throw new ArgumentException(
                          $"{badType} != {typeof(DbContext)}",
                          nameof(dbContextTypes));
            }

            // passed tests, check configuration
            if (options != null)
            {
                QueryExprSerializer.ConfigureDefaults(options);
            }

            if (rules != null || noDefaultRules == true)
            {
                QueryExprSerializer.ConfigureRules(rules, noDefaultRules);
            }

            var appBuilder = endpointRouteBuilder.CreateApplicationBuilder();

            appBuilder.UseMiddleware <ExpressionPowerToolsEFCoreMiddleware>(
                pattern.RawText,
                dbContextTypes);
            return(endpointRouteBuilder.Map(pattern, appBuilder.Build())
                   .WithDisplayName($"Expression Power Tools Serialization Pipeline"));
        }