static async Task Main(string[] args) { var connection = new HubConnectionBuilder() .WithUrl("http://localhost:5000/sample") .AddNewtonsoftJsonProtocol(s => s.PayloadSerializerSettings.TypeNameHandling = Newtonsoft.Json.TypeNameHandling.Objects) .Build(); await Task.Delay(5000); await connection.StartAsync(); var x = new QxAsyncQueryClient(new SignalRAsyncQueryServiceProvider(connection)); var range = x.GetEnumerable <int, int, int>("Range"); var r1 = range(0, 10); var r2 = range(10, 10); //var q = r1.Zip(r2); var q = await r1.Zip(r2).Skip(1).Take(1).SingleAsync(); //var q = x.GetEnumerable<int, int, int>("Range")(0,20).Where(n => n % 2 == 0).Select(x => x * 2); //await q.ForEachAsync(n => Console.WriteLine("Hello you: " + n)); Console.WriteLine("Hello you: " + q); }
// TODO: Support inlining of expressions so this passes // e.g. https://referencesource.microsoft.com/#system.data.linq/SqlClient/Query/Funcletizer.cs,ccef8437bc51e04e // e.g. https://github.com/aspnet/EntityFrameworkCore/blob/98f41f7cc483d1688c23017fbc495a709f308cfb/src/EFCore/Query/ExpressionVisitors/Internal/ParameterExtractingExpressionVisitor.cs#L101 // e.g. https://github.com/RxDave/Qactive/blob/6cd5a058082562128d51c50e3ac8bd393ea6015e/Source/Qactive/LocalEvaluationVisitor.cs public void Should_inline_etcetera() { var serviceProvider = new CapturingAsyncQueryServiceProvider(); var client = new QxAsyncQueryClient(serviceProvider: serviceProvider); _ = client.GetEnumerable <string, int>("Test1")("A").SelectMany(l => GetQueryableFromLocalMethod(client, "Test2", "B").Select(r => l + r)).GetAsyncEnumerator(); }
public void GetEnumerable1_should_refer_to_enumerables_as_unbound_parameters() { var serviceProvider = new CapturingAsyncQueryServiceProvider(); var client = new QxAsyncQueryClient(serviceProvider: serviceProvider); _ = client.GetEnumerable <int>("Test").GetAsyncEnumerator(); AssertIsKnownResourceInvocation( actualExpression: serviceProvider.CapturedExpression, expectedKnownResourceType: typeof(Func <IAsyncQueryable <int> >), expectedKnownResourceName: "Test"); }
public void GetEnumerable3_should_refer_to_enumerables_as_unbound_parameters() { var serviceProvider = new CapturingAsyncQueryServiceProvider(); var client = new QxAsyncQueryClient(serviceProvider: serviceProvider); _ = client.GetEnumerable <string, bool, int>("Test")("1", false).GetAsyncEnumerator(); AssertIsKnownResourceInvocation( actualExpression: serviceProvider.CapturedExpression, expectedKnownResourceType: typeof(Func <string, bool, IAsyncQueryable <int> >), expectedKnownResourceName: "Test", /* expectedArguments: */ (typeof(string), "1"), (typeof(bool), false)); }
public void Should_rewrite_simple_parameter_expression_to_invocation() { var range = AsyncEnumerable.Range(0, 10); Expression <Func <IAsyncQueryable <int> > > source = () => range.AsAsyncQueryable(); var client = new QxAsyncQueryClient(new NotImplementedAsyncQueryServiceProvider()); var query = client.GetEnumerable <int>("Range"); var bindings = CreateBindings((query, source)); var result = Rewrite(query.Expression, bindings); var invoke = Expression.Lambda <Func <IAsyncQueryable <int> > >(result).Compile(); Assert.Equal(range.ToEnumerable(), invoke().ToEnumerable()); }
public void Should_rewrite_parameter_expressions_with_arguments_to_invocations() { var start = 0; var count = 10; Func <int, int, IAsyncEnumerable <int> > range = (start, count) => AsyncEnumerable.Range(start, count); Expression <Func <int, int, IAsyncQueryable <int> > > source = (start, count) => range(start, count).AsAsyncQueryable(); var client = new QxAsyncQueryClient(new NotImplementedAsyncQueryServiceProvider()); var query = client.GetEnumerable <int, int, int>("Range")(start, count); var bindings = CreateBindings((query, source)); var result = Rewrite(query.Expression, bindings); var invoke = Expression.Lambda <Func <IAsyncQueryable <int> > >(result).Compile(); Assert.Equal(range(start, count).ToEnumerable(), invoke().ToEnumerable()); }
public void Should_rewrite_multiple_parameter_expressions_to_invocations() { var range1 = AsyncEnumerable.Range(0, 10); var range2 = AsyncEnumerable.Range(10, 10); Expression <Func <IAsyncQueryable <int> > > source1 = () => range1.AsAsyncQueryable(); Expression <Func <IAsyncQueryable <int> > > source2 = () => range2.AsAsyncQueryable(); var client = new QxAsyncQueryClient(new NotImplementedAsyncQueryServiceProvider()); var querySource1 = client.GetEnumerable <int>("Range1"); var querySource2 = client.GetEnumerable <int>("Range2"); var bindings = CreateBindings((querySource1, source1), (querySource2, source2)); var query = querySource1.Join(querySource2, x => x, y => y, (x, y) => x + y); var expected = range1.Join(range2, x => x, y => y, (x, y) => x + y); var result = Rewrite(query.Expression, bindings); var invoke = Expression.Lambda <Func <IAsyncQueryable <int> > >(result).Compile(); Assert.Equal(expected.ToEnumerable(), invoke().ToEnumerable()); }
public void GetEnumerable1_should_replace_closed_over_GetEnumerable1_calls_with_unbound_parameters() { var serviceProvider = new CapturingAsyncQueryServiceProvider(); var client = new QxAsyncQueryClient(serviceProvider: serviceProvider); _ = client.GetEnumerable <int>("Test1").SelectMany(l => client.GetEnumerable <int>("Test2").Select(r => l + r)).GetAsyncEnumerator(); Assert.Equal(ExpressionType.Call, serviceProvider.CapturedExpression.NodeType); var methodCallExpression = (MethodCallExpression)serviceProvider.CapturedExpression; var test1Expression = methodCallExpression.Arguments[0]; var test2Expression = ((MethodCallExpression)((LambdaExpression)((UnaryExpression)methodCallExpression.Arguments[1]).Operand).Body).Arguments[0]; AssertIsKnownResourceInvocation( actualExpression: test1Expression, expectedKnownResourceType: typeof(Func <IAsyncQueryable <int> >), expectedKnownResourceName: "Test1"); AssertIsKnownResourceInvocation( actualExpression: test2Expression, expectedKnownResourceType: typeof(Func <IAsyncQueryable <int> >), expectedKnownResourceName: "Test2"); }
private static async Task RunQueryable() { var connection = await Connect("http://localhost:60591/queryable-shares"); var client = new QxAsyncQueryClient(new DefaultAsyncQueryServiceProvider(connection)); var query = client.GetEnumerable <SharePrice>("SharePrices") .Where(sp => sp.Symbol == "MSFT") // Get the market cap .SelectMany(sp => client.GetEnumerable <SharesOutstanding>("SharesOutstanding") .Where(so => so.Symbol == sp.Symbol) .Select(so => new { so.Symbol, MarketCap = sp.Price * so.Count })) // Find the name .SelectMany(mc => client.GetEnumerable <Listing>("Listings") .Where(ls => ls.Symbol == mc.Symbol) .Select(ls => ValueTuple.Create(mc.Symbol, ls.Name, mc.MarketCap))); var query2 = from sp in client.GetEnumerable <SharePrice>("SharePrices") where sp.Symbol == "MSFT" from so in client.GetEnumerable <SharesOutstanding>("SharesOutstanding") where so.Symbol == sp.Symbol from ls in client.GetEnumerable <Listing>("Listings") where ls.Symbol == sp.Symbol //select new { ls.Symbol, ls.Name, MarketCap = sp.Price * so.Count }; select ValueTuple.Create(ls.Symbol, ls.Name, sp.Price *so.Count); //var query3 = query2.AsAsyncEnumerable().Select(t => new { Symbol = t.Item1, Name = t.Item2, MarketCap = t.Item3 }); await foreach (var element in query2) { Console.WriteLine($"{element.Item2} ({element.Item1}): {element.Item3.ToString("C")}"); //Console.WriteLine($"{element.Name} ({element.Symbol}): {element.MarketCap.ToString("C")}"); } }