Interact with MongoDB Atlas in an AWS Lambda Function Using C#
Rate this tutorial
AWS Lambda is an excellent choice for C# developers looking for a solid serverless solution with many integration options with the rest of the AWS ecosystem. When a database is required, reading and writing to MongoDB Atlas at lightning speed is effortless because Atlas databases can be instantiated in the same data center as your AWS Lambda function.
In this tutorial, we will learn how to create a C# serverless function that efficiently manages the number of MongoDB Atlas connections to make your Lambda function as scalable as possible.
- Knowledge of the C# programming language.
- A MongoDB Atlas cluster with sample data, network access (firewall), and user roles already configured.
This step-by-step MongoDB Atlas tutorial will guide you through creating an Atlas database (free tier available) and loading the sample data.
We will open the network access to any incoming IP to keep this tutorial simple and make it work with the free Atlas cluster tier. Here's how to add an IP to your Atlas project. Adding 0.0.0.0 means that any external IP can access your cluster.
In a production environment, you should restrict access and follow best MongoDB security practices, including using network peering between AWS Lambda and MongoDB Atlas. The free cluster tier does not support peering.
In Visual Studio, create a basic AWS lambda project using the "AWS Lambda Project (.NET Core - C#)" project template with the "Empty Function" blueprint. We'll use that as the basis of this tutorial. Here's the official AWS tutorial to create such a project, but essentially:
- Open Visual Studio, and on the File menu, choose New, Project.
- Create a new "AWS Lambda Project (.NET Core - C#)" project.
- We'll name the project "AWSLambda1."
Follow the official AWS tutorial above to make sure that you can upload the project to Lambda and that it runs. If it does, we're ready to make changes to connect to MongoDB from AWS Lambda!
In our project, the main class is called
Function
. It will be instantiated every time the Lambda function is triggered. Inside, we have a method called FunctionHandler
, (Function:: FunctionHandler
), which we will designate to Lambda as the entry point.Connecting to MongoDB requires adding the MongoDB.Driver (by MongoDB Inc) package in your project's packages.
Next, add the following namespaces at the top of your source file:
1 using MongoDB.Bson; 2 using MongoDB.Driver;
In the Function class, we will declare a static MongoClient member. Having it as a
static
member is crucial because we want to share it across multiple instances that AWS Lambda could spawn.Although we don't have complete control over, or visibility into, the Lambda serverless environment, this is the best practice to keep the number of connections back to the Atlas cluster to a minimum.
If we did not declare MongoClient as
static
, each class instance would create its own set of resources. Instead, the static MongoClient is shared among multiple class instances after a first instance was created (warm start). You can read more technical details about managing MongoDB Atlas connections with AWS Lambda.We will also add a
CreateMongoClient()
method that initializes the MongoDB client when the class is instantiated. Now, things should look like this:1 public class Function 2 { 3 private static MongoClient? Client; 4 private static MongoClient CreateMongoClient() 5 { 6 var mongoClientSettings = MongoClientSettings.FromConnectionString(Environment.GetEnvironmentVariable("MONGODB_URI")); 7 return new MongoClient(mongoClientSettings); 8 } 9 10 static Function() 11 { 12 Client = CreateMongoClient(); 13 } 14 ... 15 }
To keep your MongoDB credentials safe, your connection string can be stored in an AWS Lambda environment variable. The connection string looks like this below, and here's how to get it in Atlas.
mongodb+srv://USER:PASSWORD@INSTANCENAME.owdak.mongodb.net/?retryWrites=true&w=majority
Note: Visual Studio might store the connection string with your credentials into a aws-lambda-tools-defaults.json file at some point, so don't include that in a code repository.
If you want to use environment variables in the Mock Lambda Test Tool, you must create a specific "Mock Lambda Test Tool" profile with its own set of environment variables in
aws-lambda-tools-defaults.json
(here's an example).You can learn more about AWS Lambda environment variables. However, be aware that such variables can be set from within your Visual Studio when publishing to AWS Lambda or directly in the AWS management console on your AWS Lambda function page.
For testing purposes, and if you don't want to bother, some people hard-code the connection string as so:
1 var mongoClientSettings = FromConnectionString("mongodb+srv://USER:PASSWORD@instancename.owdak.mongodb.net/?retryWrites=true&w=majority");
Finally, we can modify the FunctionHandler() function to read the first document from the sample_airbnb.listingsAndReviews database and collection we preloaded in the prerequisites.
The try/catch statements are not mandatory, but they can help detect small issues such as the firewall not being set up, or other configuration errors.
1 public string FunctionHandler(string input, ILambdaContext context) 2 { 3 if (Client != null) 4 { 5 try 6 { 7 var database = Client.GetDatabase("sample_airbnb"); 8 var collection = database.GetCollection<BsonDocument>("listingsAndReviews"); 9 var result = collection.Find(FilterDefinition<BsonDocument>.Empty).First(); 10 return result.ToString(); 11 } 12 catch 13 { 14 return "Handling failed"; 15 } 16 } else 17 { 18 return "DB not initialized"; 19 } 20 }
Using the "listingsAndReviews" collection (a "table" in SQL jargon) in the "sample_airbnb" database, the code fetches the first document of the collection.
collection.Find()
normally takes a MongoDB Query built as a BsonDocument, but in this case, we only need an empty query.It's time to upload it to AWS Lambda. In the Solution Explorer, right-click on the project and select "Publish to AWS Lambda." Earlier, you might have done this while setting up the project using the official AWS Lambda C# tutorial.
If this is the first time you're publishing this function, take the time to give it a name (we use "mongdb-csharp-function-001"). It will be utilized during the initial Lambda function creation.
In the screenshot below, the AWS Lambda function Handler ("Handler") information is essential as it tells Lambda which method to call when an event is triggered. The general format is Assembly::Namespace.ClassName::MethodName
In our case, the handler is
AWSLambda1::AWSLambda1.Function::FunctionHandler
.If the option is checked, this dialog will save these options in the
aws-lambda-tools-defaults.json
file.Click "Next" to see the second upload screen. The most important aspect of it is the environment variables, such as the connection string.
When ready, click on "Upload." Visual Studio will create/update your Lambda function to AWS and launch a test window where you can set your sample input and execute the method to see its response.
Our Lambda function expects an input string, so we'll use the "hello" string in our Sample Input, then click the "Invoke" button. The execution's response will be sent to the "Response" field to the right. As expected, the first database record is converted into a string, as shown below.
We just learned how to build a C# AWS Lambda serverless function efficiently by creating and sharing a MongoDB client and connecting multiple class instances. If you're considering building with a serverless architecture and AWS Lambda, MongoDB Atlas is an excellent option.
The flexibility of our document model makes it easy to get started quickly and evolve your data structure over time. Create a free Atlas cluster now to try it.
If you want to learn more about our MongoDB C# driver, refer to the continuously updated documentation. You can do much more with MongoDB Atlas, and our C# Quick Start is a great first step on your MongoDB journey.