Home > Back-end >  Implement Singleton on Azure Functions with CosmosDB and Microsoft.Azure.Cosmos in C#
Implement Singleton on Azure Functions with CosmosDB and Microsoft.Azure.Cosmos in C#

Time:10-13

Actually I am trying to implement singleton on my C# Azure functions, but the official documentation at https://github.com/MicrosoftDocs/azure-docs/blob/main/articles/azure-functions/manage-connections.md#c-1 is not helping...

It says:

CosmosClient connects to an Azure Cosmos DB instance. The Azure Cosmos DB documentation recommends that you use a singleton Azure Cosmos DB client for the lifetime of your application. The following example shows one pattern for doing that in a function:

#r "Microsoft.Azure.Cosmos"
using Microsoft.Azure.Cosmos;

private static Lazy<CosmosClient> lazyClient = new Lazy<CosmosClient>(InitializeCosmosClient);
private static CosmosClient cosmosClient => lazyClient.Value;

private static CosmosClient InitializeCosmosClient()
{
    // Perform any initialization here
    var uri = "https://youraccount.documents.azure.com:443";
    var authKey = "authKey";
   
    return new CosmosClient(uri, authKey);
}

public static async Task Run(string input)
{
    Container container = cosmosClient.GetContainer("database", "collection");
    MyItem item = new MyItem{ id = "myId", partitionKey = "myPartitionKey", data = "example" };
    await container.UpsertItemAsync(document);
   
    // Rest of function
}

Also, create a file named "function.proj" for your trigger and add the below content :

<Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
       <TargetFramework>netcoreapp3.1</TargetFramework>
   </PropertyGroup>
   <ItemGroup>
       <PackageReference Include="Microsoft.Azure.Cosmos" Version="3.23.0" />
   </ItemGroup>
</Project>

Just to start I am not familiar with naything that's starts with a "#"R" Also, what file name must be the code ? And where to create the .proj file ? Same folder of my azure functions folder ? And after all ? How to consume what I produced ?

I will really appreciate if someone supply me a step-by-step about how to implement this on my current project. Thanks in advance !

CodePudding user response:

I believe the #r comes from .csx (C# script) files. I personally have never used this way of building Azure Functions, but you can read more about it on the official Azure Functions C# script (.csx) developer reference.

Regarding the folder/file structure, it can vary, depending on the language you use to build your functions. You can read more about it on the official Folder Structure page.

My recommendation is to build your functions using C# (compiled), which is also Microsoft's recommended way of building Azure Functions with C#. This way, you can do things as you would do normally in C#. One of the benefits includes built-in dependency injection. Using dependency injection, you could register your CosmosClient as a Singleton in one line of code and directly inject it in your functions, through the constructor (similarly to how it's done in ASP.NET Core applications).

There is an example code on the official dependency injection in .NET Azure Functions page for how to register services and consume them in your function(s).

In order to "consume" your created functions, it depends on the environment. If you are referring on how to test your functions locally, you can read the Code and test Azure Functions locally article by Microsoft that explains in detail how to set up your local environment. Also, if you are using Visual Studio or Visual Studio Code to create your project, it has a lot of pre-made templates for various triggers that can speed up your development. They are well explained in the next two articles Visual Studio Code development and Visual Studio development.

Lastly, my answer might be a little long and a lot of theory, but I believe that Microsoft has explained the whole process very well. I find it very hard to beat them, which is why I strongly recommend you to go over the entire documentation of Azure Functions. It explains the process from start to end, including local development, debugging, deployment, monitoring and more. I linked a few resources that you were interested in, but there is a lot more information in there that might be helpful to you.

CodePudding user response:

To add to the other very detailed and great answer, there is a full project example with Singleton in Azure Functions on the Cosmos DB .NET SDK repository: https://github.com/Azure/azure-cosmos-dotnet-v3/tree/master/Microsoft.Azure.Cosmos.Samples/Usage/AzureFunctions

It entails registering the Singleton:

public class Startup : FunctionsStartup
{
    private static readonly IConfigurationRoot configuration = new ConfigurationBuilder()
            .SetBasePath(Environment.CurrentDirectory)
            .AddJsonFile("AppSettings.json", optional: true, reloadOnChange: true)
            .AddEnvironmentVariables()
            .Build();

    public override void Configure(IFunctionsHostBuilder builder)
    {
        // Register the CosmosClient as a Singleton

        builder.Services.AddSingleton((s) => {
            string endpoint = configuration["EndPointUrl"];
            if (string.IsNullOrEmpty(endpoint))
            {
                throw new ArgumentNullException("Please specify a valid endpoint in the appSettings.json file or your Azure Functions Settings.");
            }

            string authKey = configuration["AuthorizationKey"];
            if (string.IsNullOrEmpty(authKey) || string.Equals(authKey, "Super secret key"))
            {
                throw new ArgumentException("Please specify a valid AuthorizationKey in the appSettings.json file or your Azure Functions Settings.");
            }

            CosmosClientBuilder configurationBuilder = new CosmosClientBuilder(endpoint, authKey);
            return configurationBuilder
                    // Add custom configuration here
                    .Build();
        });
    }
}

Then your Functions can receive it on their constructor:

private CosmosClient cosmosClient;
public MyFunctionClass(CosmosClient cosmosClient)
{
    this.cosmosClient = cosmosClient;
}


[FunctionName("MyFunction")]
public async Task<IActionResult> Run(
    [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
    ILogger log) {

// use this.cosmosClient here
  • Related