예제 #1
0
        public void CreateQueryRequest_WithAggregate_ReturnsQueryWrappedInQueryRequest()
        {
            // Arrange

            var bucket = new Mock <IBucket>();

            bucket.Setup(m => m.Name).Returns("default");
            bucket.Setup(m => m.Configuration).Returns(new BucketConfiguration()
            {
                PoolConfiguration = new PoolConfiguration(new ClientConfiguration())
            });
            bucket.Setup(m => m.Cluster).Returns(new Mock <ICluster>().Object);

            var context = new BucketContext(bucket.Object);
            var query   = context.Query <Beer>().Where(p => p.Name == "name");

            // Act

            var result = LinqQueryRequest.CreateQueryRequest(query, p => p.Average(q => q.Abv));

            // Assert

            const string queryStr = "SELECT AVG(`Extent1`.`abv`) as `result` FROM `default` as `Extent1` WHERE (`Extent1`.`name` = 'name')";

            Assert.NotNull(result);
            Assert.AreEqual(queryStr, result.GetOriginalStatement());
            Assert.True(result.ScalarResultBehavior.ResultExtractionRequired);
        }
예제 #2
0
        /// <summary>
        /// Execute a Couchbase query asynchronously.
        /// </summary>
        /// <typeparam name="T">Type being queried.</typeparam>
        /// <typeparam name="TResult">Type returned by <paramref name="additionalExpression"/>.</typeparam>
        /// <param name="source">Query to execute asynchronously.  Must be a Couchbase LINQ query.</param>
        /// <param name="additionalExpression">Additional expressions to apply to the query before executing.  Typically used for aggregates.</param>
        /// <returns>Task which contains the query result when completed.</returns>
        /// <remarks>
        /// <para>The expression contained in <paramref name="additionalExpression"/> is applied to the query before
        /// it is executed asynchrounously.  Typically, this would be used to apply an aggregate, First, Single,
        /// or other operation to the query that normall  triggers immediate query execution.  Passing these actions
        /// in <paramref name="additionalExpression"/> delays their execution so that they can be handled asynchronously.</para>
        /// <para><paramref name="additionalExpression"/> must return a scalar value or a single object.  It should not return another
        /// instance of <see cref="IQueryable{T}"/>.</para>
        /// </remarks>
        /// <example>
        /// var document = await query.ExecuteAsync(query => query.First());
        /// </example>
        /// <example>
        /// var avg = await query.ExecuteAsync(query => query.Average(p => p.Abv));
        /// </example>
        public static async Task <TResult> ExecuteAsync <T, TResult>(this IQueryable <T> source,
                                                                     Expression <Func <IQueryable <T>, TResult> > additionalExpression)
        {
            if (source is EnumerableQuery)
            {
                // Allow ExecuteAsync to simply run synchronously when executed against an in-memory collection
                // This supports injecting mock IBucketContext instances into unit tests of business logic
                // https://github.com/couchbaselabs/Linq2Couchbase/issues/191

                var additionalFunction = additionalExpression.Compile();
                return(additionalFunction(source));
            }

            EnsureBucketQueryable(source, "ExecuteAsync", "source");

            if (typeof(TResult).GetTypeInfo().IsGenericTypeDefinition&&
                (typeof(TResult).GetGenericTypeDefinition() == typeof(IQueryable <>)))
            {
                throw new ArgumentException("additionalExpression must return a scalar value, not IQueryable.", "additionalExpression");
            }

            var queryRequest = LinqQueryRequest.CreateQueryRequest(source, additionalExpression);

            return(await
                       ((IBucketQueryExecutorProvider)source).BucketQueryExecutor.ExecuteSingleAsync <TResult>(queryRequest)
                   .ConfigureAwait(false));
        }
예제 #3
0
        public void CreateQueryRequest_First_ReturnsQueryWrappedInQueryRequest()
        {
            // Arrange

            var bucket = new Mock <IBucket>();

            bucket.Setup(m => m.Name).Returns("default");
            bucket.Setup(m => m.Configuration).Returns(new BucketConfiguration()
            {
                PoolConfiguration = new PoolConfiguration(new ClientConfiguration())
            });
            bucket.Setup(m => m.Cluster).Returns(new Mock <ICluster>().Object);

            var context = new BucketContext(bucket.Object);
            var query   = context.Query <Brewery>().Where(p => p.Name == "name");

            // Act

            var result = LinqQueryRequest.CreateQueryRequest(query, p => p.First());

            // Assert

            const string queryStr = "SELECT `Extent1`.* FROM `default` as `Extent1` WHERE (`Extent1`.`name` = 'name') LIMIT 1";

            Assert.NotNull(result);
            Assert.AreEqual(queryStr, result.GetOriginalStatement());
            Assert.False(result.ReturnDefaultWhenEmpty);
        }
예제 #4
0
        public void CreateQueryRequest_ScanWait_HasSetting()
        {
            // Arrange

            var bucket = new Mock <IBucket>();

            bucket.Setup(m => m.Name).Returns("default");
            bucket.Setup(m => m.Configuration).Returns(new BucketConfiguration()
            {
                PoolConfiguration = new PoolConfiguration(new ClientConfiguration())
            });
            bucket.Setup(m => m.Cluster).Returns(new Mock <ICluster>().Object);

            var scanWait = TimeSpan.FromMinutes(1);

            var context = new BucketContext(bucket.Object);
            var query   = context.Query <Brewery>().ScanWait(scanWait).Where(p => p.Name == "name");

            // Act

            var result = LinqQueryRequest.CreateQueryRequest(query);

            // Assert

            Assert.NotNull(result);
            Assert.AreEqual(scanWait.TotalMilliseconds + "ms", result.GetFormValues()["scan_wait"]);
        }
예제 #5
0
        public void CreateQueryRequest_ScanConsistency_HasSetting()
        {
            // Arrange

            var bucket = new Mock <IBucket>();

            bucket.Setup(m => m.Name).Returns("default");
            bucket.Setup(m => m.Configuration).Returns(new BucketConfiguration()
            {
                PoolConfiguration = new PoolConfiguration(new ClientConfiguration())
            });
            bucket.Setup(m => m.Cluster).Returns(new Mock <ICluster>().Object);

            var context = new BucketContext(bucket.Object);
            var query   = context.Query <Brewery>().ScanConsistency(ScanConsistency.RequestPlus).Where(p => p.Name == "name");

            // Act

            var result = LinqQueryRequest.CreateQueryRequest(query);

            // Assert

            Assert.NotNull(result);
            Assert.AreEqual("request_plus", result.GetFormValues()["scan_consistency"]);
        }
예제 #6
0
        public void CreateQueryRequest_All_ReturnsQueryWrappedInQueryRequest()
        {
            // Arrange

            var bucket = new Mock <IBucket>();

            bucket.Setup(m => m.Name).Returns("default");
            bucket.Setup(m => m.Configuration).Returns(new BucketConfiguration()
            {
                PoolConfiguration = new PoolConfiguration(new ClientConfiguration())
            });
            bucket.Setup(m => m.Cluster).Returns(new Mock <ICluster>().Object);

            var context = new BucketContext(bucket.Object);
            var query   = context.Query <Brewery>();

            // Act

            var result = LinqQueryRequest.CreateQueryRequest(query, p => p.All(q => q.Name == "name"));

            // Assert

            const string queryStr = "SELECT false as result FROM `default` as `Extent1` WHERE NOT ((`Extent1`.`name` = 'name')) LIMIT 1";

            Assert.NotNull(result);
            Assert.AreEqual(queryStr, result.GetOriginalStatement());
            Assert.True(result.ScalarResultBehavior.ResultExtractionRequired);
            Assert.AreEqual(true, result.ScalarResultBehavior.NoRowsResult);
        }
예제 #7
0
        /// <summary>
        /// Execute a Couchbase query asynchronously.
        /// </summary>
        /// <typeparam name="T">Type being queried.</typeparam>
        /// <param name="source">Query to execute asynchronously.  Must be a Couchbase LINQ query.</param>
        /// <returns>Task which contains the query result when completed.</returns>
        /// <example>
        /// var results = await query.ExecuteAsync();
        /// </example>
        public static async Task <IEnumerable <T> > ExecuteAsync <T>(this IQueryable <T> source)
        {
            EnsureBucketQueryable(source, "ExecuteAsync", "source");

            var queryRequest = LinqQueryRequest.CreateQueryRequest(source);

            return(await
                       ((IBucketQueryExecutorProvider)source).BucketQueryExecutor.ExecuteCollectionAsync <T>(queryRequest)
                   .ConfigureAwait(false));
        }
예제 #8
0
        /// <summary>
        /// Execute a Couchbase query asynchronously.
        /// </summary>
        /// <typeparam name="T">Type being queried.</typeparam>
        /// <typeparam name="TResult">Type returned by <paramref name="additionalExpression"/>.</typeparam>
        /// <param name="source">Query to execute asynchronously.  Must be a Couchbase LINQ query.</param>
        /// <param name="additionalExpression">Additional expressions to apply to the query before executing.  Typically used for aggregates.</param>
        /// <returns>Task which contains the query result when completed.</returns>
        /// <remarks>
        /// <para>The expression contained in <paramref name="additionalExpression"/> is applied to the query before
        /// it is executed asynchrounously.  Typically, this would be used to apply an aggregate, First, Single,
        /// or other operation to the query that normall  triggers immediate query execution.  Passing these actions
        /// in <paramref name="additionalExpression"/> delays their execution so that they can be handled asynchronously.</para>
        /// <para><paramref name="additionalExpression"/> must return a scalar value or a single object.  It should not return another
        /// instance of <see cref="IQueryable{T}"/>.</para>
        /// </remarks>
        /// <example>
        /// var document = await query.ExecuteAsync(query => query.First());
        /// </example>
        /// <example>
        /// var avg = await query.ExecuteAsync(query => query.Average(p => p.Abv));
        /// </example>
        public static async Task <TResult> ExecuteAsync <T, TResult>(this IQueryable <T> source,
                                                                     Expression <Func <IQueryable <T>, TResult> > additionalExpression)
        {
            EnsureBucketQueryable(source, "ExecuteAsync", "source");

            if (typeof(TResult).GetTypeInfo().IsGenericTypeDefinition&&
                (typeof(TResult).GetGenericTypeDefinition() == typeof(IQueryable <>)))
            {
                throw new ArgumentException("additionalExpression must return a scalar value, not IQueryable.", "additionalExpression");
            }

            var queryRequest = LinqQueryRequest.CreateQueryRequest(source, additionalExpression);

            return(await
                       ((IBucketQueryExecutorProvider)source).BucketQueryExecutor.ExecuteSingleAsync <TResult>(queryRequest)
                   .ConfigureAwait(false));
        }
예제 #9
0
        /// <summary>
        /// Execute a Couchbase query asynchronously.
        /// </summary>
        /// <typeparam name="T">Type being queried.</typeparam>
        /// <param name="source">Query to execute asynchronously.  Must be a Couchbase LINQ query.</param>
        /// <returns>Task which contains the query result when completed.</returns>
        /// <example>
        /// var results = await query.ExecuteAsync();
        /// </example>
        public static async Task <IEnumerable <T> > ExecuteAsync <T>(this IQueryable <T> source)
        {
            if (source is EnumerableQuery)
            {
                // Allow ExecuteAsync to simply run synchronously when executed against an in-memory collection
                // This supports injecting mock IBucketContext instances into unit tests of business logic
                // https://github.com/couchbaselabs/Linq2Couchbase/issues/191

                return(source.AsEnumerable());
            }

            EnsureBucketQueryable(source, "ExecuteAsync", "source");

            var queryRequest = LinqQueryRequest.CreateQueryRequest(source);

            return(await
                       ((IBucketQueryExecutorProvider)source).BucketQueryExecutor.ExecuteCollectionAsync <T>(queryRequest)
                   .ConfigureAwait(false));
        }