Beispiel #1
0
        internal DocumentClient BindForClient(CosmosDBAttribute attribute)
        {
            string           resolvedConnectionString = ResolveConnectionString(attribute.ConnectionStringSetting);
            ICosmosDBService service = GetService(resolvedConnectionString, attribute.PreferredLocations, attribute.UseMultipleWriteLocations);

            return(service.GetClient());
        }
Beispiel #2
0
        internal DocumentClient BindForClient(CosmosDBAttribute attribute)
        {
            string           resolvedConnectionString = ResolveConnectionString(attribute.ConnectionStringSetting);
            ICosmosDBService service = GetService(resolvedConnectionString);

            return(service.GetClient());
        }
        public async Task <IEnumerable <T> > ConvertAsync(CosmosDBAttribute attribute, CancellationToken cancellationToken)
        {
            CosmosDBContext context = _config.CreateContext(attribute);

            Uri collectionUri = UriFactory.CreateDocumentCollectionUri(context.ResolvedAttribute.DatabaseName, context.ResolvedAttribute.CollectionName);

            List <T> finalResults = new List <T>();

            string continuation = null;

            SqlQuerySpec sqlSpec = new SqlQuerySpec
            {
                QueryText  = context.ResolvedAttribute.SqlQuery,
                Parameters = context.ResolvedAttribute.SqlQueryParameters ?? new SqlParameterCollection()
            };

            do
            {
                DocumentQueryResponse <T> response = await context.Service.ExecuteNextAsync <T>(collectionUri, sqlSpec, continuation);

                finalResults.AddRange(response.Results);
                continuation = response.ResponseContinuation;
            }while (!string.IsNullOrEmpty(continuation));

            return(finalResults);
        }
 internal void ValidateConnection(CosmosDBAttribute attribute, Type paramType)
 {
     if (string.IsNullOrEmpty(attribute.ConnectionStringSetting))
     {
         string attributeProperty = $"{nameof(CosmosDBAttribute)}.{nameof(CosmosDBAttribute.ConnectionStringSetting)}";
         throw new InvalidOperationException(
                   $"The CosmosDB connection string must be set via the {attributeProperty} property.");
     }
 }
        internal CosmosDBBindingContext CreateContext(CosmosDBAttribute attribute)
        {
            CosmosClient client = GetService(attribute.ConnectionStringSetting, attribute.CurrentRegion);

            return(new CosmosDBBindingContext
            {
                CosmosClient = client,
                ResolvedAttribute = attribute,
            });
        }
Beispiel #6
0
 internal void ValidateConnection(CosmosDBAttribute attribute, Type paramType)
 {
     if (string.IsNullOrEmpty(_options.ConnectionString) &&
         string.IsNullOrEmpty(attribute.ConnectionStringSetting))
     {
         string attributeProperty = $"{nameof(CosmosDBAttribute)}.{nameof(CosmosDBAttribute.ConnectionStringSetting)}";
         string optionsProperty   = $"{nameof(CosmosDBOptions)}.{nameof(CosmosDBOptions.ConnectionString)}";
         throw new InvalidOperationException(
                   $"The CosmosDB connection string must be set either via the '{Constants.DefaultConnectionStringName}' IConfiguration connection string, via the {attributeProperty} property or via {optionsProperty}.");
     }
 }
Beispiel #7
0
        internal CosmosDBContext CreateContext(CosmosDBAttribute attribute)
        {
            string resolvedConnectionString = ResolveConnectionString(attribute.ConnectionStringSetting);

            ICosmosDBService service = GetService(resolvedConnectionString, attribute.PreferredLocations, attribute.UseMultipleWriteLocations);

            return(new CosmosDBContext
            {
                Service = service,
                ResolvedAttribute = attribute,
            });
        }
Beispiel #8
0
 internal void ValidateConnection(CosmosDBAttribute attribute, Type paramType)
 {
     if (string.IsNullOrEmpty(_options.ConnectionString) &&
         string.IsNullOrEmpty(attribute.ConnectionStringSetting) &&
         string.IsNullOrEmpty(_defaultConnectionString))
     {
         throw new InvalidOperationException(
                   string.Format(CultureInfo.CurrentCulture,
                                 "The CosmosDB connection string must be set either via a '{0}' app setting, via the CosmosDBAttribute.ConnectionStringSetting property or via CosmosDBConfiguration.ConnectionString.",
                                 AzureWebJobsCosmosDBConnectionStringName));
     }
 }
Beispiel #9
0
        internal CosmosDBContext CreateContext(CosmosDBAttribute attribute)
        {
            string resolvedConnectionString = ResolveConnectionString(attribute.ConnectionStringSetting);

            ICosmosDBService service = GetService(resolvedConnectionString);

            return(new CosmosDBContext
            {
                Service = service,
                ResolvedAttribute = attribute,
            });
        }
Beispiel #10
0
        internal Task <IValueBinder> BindForItemAsync(CosmosDBAttribute attribute, Type type)
        {
            if (string.IsNullOrEmpty(attribute.Id))
            {
                throw new InvalidOperationException("The 'Id' property of a CosmosDB single-item input binding cannot be null or empty.");
            }

            CosmosDBContext context = CreateContext(attribute);

            Type         genericType = typeof(CosmosDBItemValueBinder <>).MakeGenericType(type);
            IValueBinder binder      = (IValueBinder)Activator.CreateInstance(genericType, context);

            return(Task.FromResult(binder));
        }
Beispiel #11
0
        public static CosmosDBContext CreateContext(ICosmosDBService service, bool createIfNotExists = false,
                                                    string partitionKeyPath = null, int throughput = 0)
        {
            CosmosDBAttribute attribute = new CosmosDBAttribute(CosmosDBTestUtility.DatabaseName, CosmosDBTestUtility.CollectionName)
            {
                CreateIfNotExists    = createIfNotExists,
                PartitionKey         = partitionKeyPath,
                CollectionThroughput = throughput
            };

            return(new CosmosDBContext
            {
                Service = service,
                ResolvedAttribute = attribute
            });
        }
Beispiel #12
0
        public static async void Run([ServiceBusTrigger("msciprovider", "mscicompany", Connection = "MsciConnectionString")] string mySbMsg,
                                     IBinder binder, ILogger log)
        {
            var collectionName = "CandriamContainer";

            var attribute = new CosmosDBAttribute("CandriamDB", collectionName)
            {
                CreateIfNotExists       = true,
                ConnectionStringSetting = "CosmosDBConnection",
            };

            var collector = await binder.BindAsync <IAsyncCollector <dynamic> >(attribute);

            await collector.AddAsync(new { Message = mySbMsg, id = Guid.NewGuid(), ProviderId = 2 });

            log.LogInformation("Document created !");
        }
Beispiel #13
0
        private static CosmosDBItemValueBinder <T> CreateBinder <T>(out Mock <ICosmosDBService> mockService, string partitionKey = null)
            where T : class
        {
            mockService = new Mock <ICosmosDBService>(MockBehavior.Strict);

            CosmosDBAttribute attribute = new CosmosDBAttribute(DatabaseName, CollectionName)
            {
                Id           = Id,
                PartitionKey = partitionKey
            };

            var context = new CosmosDBContext
            {
                ResolvedAttribute = attribute,
                Service           = mockService.Object
            };

            return(new CosmosDBItemValueBinder <T>(context));
        }
        public async Task Configuration_Caches_Clients()
        {
            // Arrange
            var config = new CosmosDBConfiguration
            {
                ConnectionString = "AccountEndpoint=https://someuri;AccountKey=c29tZV9rZXk=;",
            };
            var attribute = new CosmosDBAttribute {
                Id = "abcdef"
            };

            // Act
            var context1 = config.CreateContext(attribute);
            var context2 = config.CreateContext(attribute);
            var binder   = await config.BindForItemAsync(attribute, typeof(Item));

            // Assert
            Assert.Single(config.ClientCache);
        }
        public async Task Configuration_Caches_Clients()
        {
            // Arrange
            var options = new CosmosDBOptions {
                ConnectionString = "AccountEndpoint=https://someuri;AccountKey=c29tZV9rZXk=;"
            };
            var config    = new CosmosDBExtensionConfigProvider(new OptionsWrapper <CosmosDBOptions>(options), new DefaultCosmosDBServiceFactory(), new TestNameResolver(), NullLoggerFactory.Instance);
            var attribute = new CosmosDBAttribute {
                Id = "abcdef"
            };

            // Act
            var context1 = config.CreateContext(attribute);
            var context2 = config.CreateContext(attribute);
            var binder   = await config.BindForItemAsync(attribute, typeof(Item));

            // Assert
            Assert.Single(config.ClientCache);
        }
Beispiel #16
0
        public void TemplateBind_DuplicateParameters()
        {
            // Arrange
            PropertyInfo      propInfo          = null;
            CosmosDBAttribute resolvedAttribute = new CosmosDBAttribute();
            BindingTemplate   bindingTemplate   =
                BindingTemplate.FromString("SELECT * FROM c WHERE c.id = {foo} AND c.value = {foo}");
            Dictionary <string, object> bindingData = new Dictionary <string, object>();

            bindingData.Add("foo", "1234");
            CosmosDBSqlResolutionPolicy policy = new CosmosDBSqlResolutionPolicy();

            // Act
            string result = policy.TemplateBind(propInfo, resolvedAttribute, bindingTemplate, bindingData);

            // Assert
            Assert.Single(resolvedAttribute.SqlQueryParameters, p => p.Name == "@foo" && p.Value.ToString() == "1234");
            Assert.Equal("SELECT * FROM c WHERE c.id = @foo AND c.value = @foo", result);
        }
        public async Task ConvertAsync_RethrowsException_IfNotFound()
        {
            var builder = CreateBuilder <Item>(out Mock <ICosmosDBService> mockService);

            mockService
            .Setup(m => m.ExecuteNextAsync <Item>(_expectedUri, It.IsAny <SqlQuerySpec>(), It.IsAny <string>()))
            .ThrowsAsync(CosmosDBTestUtility.CreateDocumentClientException((HttpStatusCode)404));

            CosmosDBAttribute attribute = new CosmosDBAttribute(DatabaseName, CollectionName)
            {
                SqlQuery           = string.Empty,
                SqlQueryParameters = new SqlParameterCollection()
            };

            var ex = await Assert.ThrowsAsync <DocumentClientException>(() => builder.ConvertAsync(attribute, CancellationToken.None));

            Assert.Equal("NotFound", ex.Error.Code);

            mockService.Verify(m => m.ExecuteNextAsync <Item>(_expectedUri, It.IsAny <SqlQuerySpec>(), It.IsAny <string>()), Times.Once());
        }
Beispiel #18
0
        public async Task SetAsync_Updates_IfPropertyChanges()
        {
            // Arrange
            var mockService = new Mock <ICosmosDBService>(MockBehavior.Strict);

            Item original = new Item
            {
                Id   = "abc123",
                Text = "hello"
            };

            Item updated = new Item
            {
                Id   = "abc123",
                Text = "goodbye"
            };

            mockService
            .Setup(m => m.ReplaceDocumentAsync(_expectedUri, updated))
            .ReturnsAsync(new Document());

            CosmosDBAttribute attribute = new CosmosDBAttribute(DatabaseName, CollectionName)
            {
                Id = Id
            };

            var context = new CosmosDBContext
            {
                Service           = mockService.Object,
                ResolvedAttribute = attribute
            };

            JObject clonedOrig = CosmosDBItemValueBinder <object> .CloneItem(original);

            // Act
            await CosmosDBItemValueBinder <Item> .SetValueInternalAsync(clonedOrig, updated, context);

            // Assert
            mockService.VerifyAll();
        }
        public async Task ConvertAsync_Succeeds_NoContinuation()
        {
            var builder = CreateBuilder <Document>(out Mock <ICosmosDBService> mockService);

            mockService
            .Setup(m => m.ExecuteNextAsync <Document>(_expectedUri, It.IsAny <SqlQuerySpec>(), It.IsAny <string>()))
            .ReturnsAsync(new DocumentQueryResponse <Document>
            {
                Results = GetDocumentCollection(5),
                ResponseContinuation = null
            });

            CosmosDBAttribute attribute = new CosmosDBAttribute(DatabaseName, CollectionName)
            {
                SqlQuery           = string.Empty,
                SqlQueryParameters = new SqlParameterCollection()
            };

            var results = await builder.ConvertAsync(attribute, CancellationToken.None);

            Assert.Equal(5, results.Count());
        }
Beispiel #20
0
        internal static void ValidateInputBinding(CosmosDBAttribute attribute, Type parameterType)
        {
            bool hasSqlQuery = !string.IsNullOrEmpty(attribute.SqlQuery);
            bool hasId       = !string.IsNullOrEmpty(attribute.Id);

            if (hasSqlQuery && hasId)
            {
                throw new InvalidOperationException($"Only one of 'SqlQuery' and '{nameof(CosmosDBAttribute.Id)}' can be specified.");
            }

            if (IsSupportedEnumerable(parameterType))
            {
                if (hasId)
                {
                    throw new InvalidOperationException($"'{nameof(CosmosDBAttribute.Id)}' cannot be specified when binding to an IEnumerable property.");
                }
            }
            else if (!hasId)
            {
                throw new InvalidOperationException($"'{nameof(CosmosDBAttribute.Id)}' is required when binding to a {parameterType.Name} property.");
            }
        }
        public async Task ConvertAsync_Succeeds_WithContinuation()
        {
            var builder       = CreateBuilder <Document>(out Mock <ICosmosDBService> mockService);
            var docCollection = GetDocumentCollection(17);

            mockService
            .SetupSequence(m => m.ExecuteNextAsync <Document>(_expectedUri, It.IsAny <SqlQuerySpec>(), It.IsAny <string>()))
            .ReturnsAsync(new DocumentQueryResponse <Document>
            {
                Results = docCollection.Take(5),
                ResponseContinuation = "1"
            })
            .ReturnsAsync(new DocumentQueryResponse <Document>
            {
                Results = docCollection.Skip(5).Take(5),
                ResponseContinuation = "2"
            }).ReturnsAsync(new DocumentQueryResponse <Document>
            {
                Results = docCollection.Skip(10).Take(5),
                ResponseContinuation = "3"
            }).ReturnsAsync(new DocumentQueryResponse <Document>
            {
                Results = docCollection.Skip(15).Take(2),
                ResponseContinuation = null
            });

            CosmosDBAttribute attribute = new CosmosDBAttribute(DatabaseName, CollectionName)
            {
                SqlQuery           = string.Empty,
                SqlQueryParameters = new SqlParameterCollection()
            };

            var results = await builder.ConvertAsync(attribute, CancellationToken.None);

            Assert.Equal(17, results.Count());

            mockService.Verify(m => m.ExecuteNextAsync <Document>(_expectedUri, It.IsAny <SqlQuerySpec>(), It.IsAny <string>()), Times.Exactly(4));
        }
Beispiel #22
0
        public async Task SetAsync_Poco_SkipsUpdate_IfSame()
        {
            // Arrange
            var mockService = new Mock <ICosmosDBService>(MockBehavior.Strict);

            Item original = new Item
            {
                Id   = "abc123",
                Text = "hello"
            };

            Item updated = new Item
            {
                Id   = "abc123",
                Text = "hello"
            };

            CosmosDBAttribute attribute = new CosmosDBAttribute(DatabaseName, CollectionName)
            {
                Id = Id
            };

            var context = new CosmosDBContext
            {
                Service           = mockService.Object,
                ResolvedAttribute = attribute
            };

            JObject clonedOrig = CosmosDBItemValueBinder <object> .CloneItem(original);

            // Act
            await CosmosDBItemValueBinder <Item> .SetValueInternalAsync(clonedOrig, updated, context);

            // Assert

            // nothing on the client should be called
            mockService.VerifyAll();
        }
Beispiel #23
0
        public string TemplateBind(PropertyInfo propInfo, Attribute resolvedAttribute, BindingTemplate bindingTemplate, IReadOnlyDictionary <string, object> bindingData)
        {
            if (bindingTemplate == null)
            {
                throw new ArgumentNullException(nameof(bindingTemplate));
            }

            if (bindingData == null)
            {
                throw new ArgumentNullException(nameof(bindingData));
            }

            CosmosDBAttribute docDbAttribute = resolvedAttribute as CosmosDBAttribute;

            if (docDbAttribute == null)
            {
                throw new NotSupportedException($"This policy is only supported for {nameof(CosmosDBAttribute)}.");
            }

            // build a SqlParameterCollection for each parameter
            SqlParameterCollection paramCollection = new SqlParameterCollection();

            // also build up a dictionary replacing '{token}' with '@token'
            IDictionary <string, string> replacements = new Dictionary <string, string>();

            foreach (var token in bindingTemplate.ParameterNames.Distinct())
            {
                string sqlToken = $"@{token}";
                paramCollection.Add(new SqlParameter(sqlToken, bindingData[token]));
                replacements.Add(token, sqlToken);
            }

            docDbAttribute.SqlQueryParameters = paramCollection;

            string replacement = bindingTemplate.Bind(new ReadOnlyDictionary <string, string>(replacements));

            return(replacement);
        }
        public async Task <IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Anonymous, "GET", Route = "api/orders")]
            HttpRequest req,
            IBinder binder,
            ILogger log)
        {
            log.LogInformation("GetOrders HTTP trigger function processed a request.");

            if (!await req.CheckAuthorization("api"))
            {
                return(new UnauthorizedResult());
            }

            var cosmosDb = new CosmosDBAttribute("ordersservice", "data");

            cosmosDb.ConnectionStringSetting = "CosmosDB";

            var ordersData = await binder.BindAsync <IEnumerable <NewOrderMessage> >(cosmosDb);

            var orders = ordersData.Select(doc => doc.Order).OrderByDescending(o => o.Created).ToList();

            return(new OkObjectResult(orders));
        }
Beispiel #25
0
        public async Task SetAsync_Poco_Throws_IfIdChanges()
        {
            // Arrange
            var mockService = new Mock <ICosmosDBService>(MockBehavior.Strict);

            Item original = new Item
            {
                Id = "abc123",
            };

            Item updated = new Item
            {
                Id = "def456",
            };

            CosmosDBAttribute attribute = new CosmosDBAttribute(DatabaseName, CollectionName)
            {
                Id = Id
            };

            var context = new CosmosDBContext
            {
                Service           = mockService.Object,
                ResolvedAttribute = attribute
            };

            var originalJson = JObject.FromObject(original);

            // Act
            var ex = await Assert.ThrowsAsync <InvalidOperationException>(
                () => CosmosDBItemValueBinder <Item> .SetValueInternalAsync(originalJson, updated, context));

            // Assert
            Assert.Equal("Cannot update the 'Id' property.", ex.Message);
            mockService.Verify();
        }
 public void ValidateInputBindings_Succeeds_WithValidBindings(CosmosDBAttribute attribute, Type parameterType)
 {
     CosmosDBConfiguration.ValidateInputBinding(attribute, parameterType);
 }
Beispiel #27
0
        public IAsyncCollector <T> Convert(CosmosDBAttribute attribute)
        {
            CosmosDBContext context = _configProvider.CreateContext(attribute);

            return(new CosmosDBAsyncCollector <T>(context));
        }
 public void ValidateInputBindings_Throws_WithInvalidBindings(CosmosDBAttribute attribute, Type parameterType)
 {
     Assert.Throws <InvalidOperationException>(() => CosmosDBConfiguration.ValidateInputBinding(attribute, parameterType));
 }