
Integrating RavenDB with .NET Aspire project for enhanced development
Table of contents
Introduction
Recently, RavenDB was integrated with .NET Aspire. It helps you manage all your application dependencies, including your database, to enhance dev-time orchestration.
.NET Aspire manages well-defined app components, runs them in containers, provides pre-configured observability, and much more. In this guide, since RavenDB is now Aspire-ready, we’ll show you how to leverage it to abstract out dependencies management.
We’ll walk you through:
- Both hosting and client integrations – We’ll set up a .NET Aspire project, deploy a RavenDB server, and create an API service that interacts with the database.
- We’ll implement a fun use case inspired by the TV show Friends to demonstrate RavenDB’s capabilities, including time series, counters, and queries.
So grab a cup of coffee ☕, and let’s get started!
Setting Up RavenDB with .NET Aspire
0. Requirements
- .NET 8.0+
- Container runtime like Docker Desktop or Podman
- Visual Studio, version 17.9 or higher
- Alternatively, Rider with the .NET Aspire plugin
1. Creating an Empty .NET Aspire Application from Visual Studio
Let’s start with something simple: creating an empty .NET Aspire application in Visual Studio.
- Open Visual Studio and go to File > New > Project.
- Search for and select .NET Aspire Application.
- Choose a name for your project (e.g., RavenDBAspireExample) and click Create.
- The solution will contain multiple projects, including:
- AppHost (Manages hosting and dependencies)
- ServiceDefaults (Provides common service configurations)
2. Creating the API Service Project
Now, we may proceed with adding RavenDB integration.
- Right-click on the `RavenDBAspireExample` solution in Solution Explorer.
- Select Add > New Project.
- Choose ASP.NET Core Web API.
- Name the project `RavenDBAspireExample.ApiService`.
- Click Create.
- Ensure the project is added to the solution and appears under the solution structure.
3. Connecting the API Service to ServiceDefaults
As the APIService project runs, it’s time to link it to the ServiceDefaults project. This step is important because it helps the APIService project inherit all the necessary configurations for smooth communication within the Aspire framework.
- Right-click on the APIService project in Solution Explorer.
- Select Add > Project Reference…
- Choose the ServiceDefaults project from the list and click OK.
4. Adding RavenDB Hosting Integration and Referencing API Service in AppHost
Now, before connecting AppHost to APIService, we install the 📦 CommunityToolkit.Aspire.Hosting.RavenDB. We can do that in two ways. Add it using the command using NuGet. You can find more information here. You can use the following command to do that:
dotnet add package CommunityToolkit.Aspire.Hosting.RavenDB
Alternatively, you can install it via Visual Studio:
- Right-click on the AppHost project.
- Select Manage NuGet Packages.
- Search for `CommunityToolkit.Aspire.Hosting.RavenDB` and install it.
Make sure that after installation, the package exists under your AppHost > Dependencies > Packages:
Adding a Reference to the API Service in AppHost
We just need to add a reference to enable the AppHost project to work with the APIService project.
- Right-click on the AppHost project in Solution Explorer.
- Select Add > Project Reference….
- Choose the APIService project from the list and click OK.
Next, modify Program.cs in AppHost to register the API Service project:
using Projects;
var builder = DistributedApplication.CreateBuilder(args);
var serverResource = builder.AddRavenDB(name: "ravenServerResource");
var databaseResource = serverResource.AddDatabase(name: "ravenDatabaseResource", databaseName: "myDatabase");
builder.AddProject<RavenDBAspireExample_ApiService>("RavenApiService")
.WithReference(databaseResource)
.WaitFor(databaseResource);
builder.Build().Run();
5. Previewing the .NET Aspire Dashboard
Once the AppHost project is up and running, we can explore the .NET Aspire Dashboard, which allows us to monitor our application’s resources.
- Run the AppHost project.
- Look for the Login to Dashboard URL in the console output.
- Copy and paste the URL into your browser.
The dashboard provides:
- An overview of all running services in the Aspire application.
- Logs and metrics for debugging and monitoring.
- Access to RavenDB Studio, where you can explore the database.
Using the dashboard, you can verify that the RavenDB server is running and connected to the APIService project.
6. Adding RavenDB Client Integration
With the RavenDB client integration, your application can easily connect to a RavenDB instance and engage with its databases through the `IDocumentStore`. Let’s do it now.
Installing the Client Package
Like before, In the APIService project, install the 📦 CommunityToolkit.Aspire.RavenDB.Client NuGet package in one of two ways.
dotnet add package CommunityToolkit.Aspire.RavenDB.Client
Or via Visual Studio:
- Right-click on the APIService project.
- Select Manage NuGet Packages.
- Search for `CommunityToolkit.Aspire.RavenDB.Client` and install it.
Configuring the RavenDB Client in APIService
And then let’s modify the Program.cs file of the APIService project:
var builder = WebApplication.CreateBuilder(args);
builder.AddServiceDefaults();
builder.AddRavenDBClient(connectionName: "ravenDatabaseResource", configureSettings: settings =>
{
settings.CreateDatabase = true;
settings.DatabaseName = "myDatabase";
});
var app = builder.Build();
// here we’ll add some API endpoints shortly…
app.Run();
* Ensure the `connectionName` matches the one used in the AppHost project.
Building the API: Central Perk Coffee Tracker ☕
Great! Now that we’ve got our RavenDB server and client all set up, let’s dive in and create a fun API service to track how much coffee each of our favorite Friends characters drinks. Sounds like a fun project, doesn’t it? This example demonstrates how to:
- Store documents (Character profiles)
- Use time series (Track coffee consumption over time)
- Use counters (Keep a tally of total coffee cups per character)
- Query data (Retrieve coffee consumption statistics)
You can also check the repo here.
1. Adding Character Profiles
First, create the code to store Friends characters in the database.
app.MapPut("/characters", async (IDocumentStore documentStore) =>
{
var users = new Character[]
{
new() {Id = "characters/joey", Name = "Joey Tribbiani", FavoriteDrink = "Espresso"},
new() {Id = "characters/chandler", Name = "Chandler Bing", FavoriteDrink = "Black Coffee"},
new() {Id = "characters/ross", Name = "Ross Geller", FavoriteDrink = "Macchiato"},
new() {Id = "characters/monica", Name = "Monica Geller", FavoriteDrink = "Latte"},
new() {Id = "characters/phoebe", Name = "Phoebe Buffay-Hannigan", FavoriteDrink = "Herbal Tea"},
new() {Id = "characters/rachel", Name = "Rachel Green", FavoriteDrink = "Cappuccino"}
};
using var session = documentStore.OpenAsyncSession();
foreach (var user in users)
await session.StoreAsync(user);
await session.SaveChangesAsync();
});
2. Logging Coffee Consumption
Now, let’s record a coffee drink event in a time series and increment a counter.
app.MapPost("/characters/coffee", async (IDocumentStore documentStore, [FromQuery] string id) =>
{
var now = DateTime.UtcNow;
using var session = documentStore.OpenAsyncSession();
session.TimeSeriesFor(id, "coffee-drinks").Append(now, 1);
session.CountersFor(id).Increment("TotalCups", 1);
await session.SaveChangesAsync();
return Results.Ok($"Logged coffee drink for {id} at {now}");
});
3. Fetching Coffee Stats
This code retrieves coffee-drinking trends for a character over time.
app.MapGet("/characters/coffee-stats", async (IDocumentStore documentStore, [FromQuery] string id) =>
{
using var session = documentStore.OpenAsyncSession();
var coffeeData = await session.TimeSeriesFor(id, "coffee-drinks")
.GetAsync(DateTime.UtcNow.AddDays(-30), DateTime.UtcNow);
var totalCups = await session.CountersFor(id).GetAsync("TotalCups");
return Results.Ok(new { coffeeData, totalCups });
});
4. Finding the Top Coffee Drinker
Finally, this piece of code returns to us the character who consumed the most coffee.
app.MapGet("/top-coffee-drinker", (IDocumentStore documentStore) =>
{
using var session = documentStore.OpenSession();
var result = session.Advanced.RawQuery<CounterResult>
("from characters as c where c.\"@metadata\".\"@counters\" == \"TotalCups\" " +
"select { Name: c.Name, TotalCups: counter(c, \"TotalCups\") }")
.ToList()
.OrderByDescending(x => x.TotalCups)
.FirstOrDefault();
return Results.Ok($"The TOP coffee drinker is '{result?.Name}' with {result?.TotalCups} Total Cups!");
});
And here is the full Program.cs:
using Microsoft.AspNetCore.Mvc;
using Raven.Client.Documents;
var builder = WebApplication.CreateBuilder(args);
builder.AddServiceDefaults();
builder.AddRavenDBClient(connectionName: "ravenDatabaseResource", configureSettings: settings =>
{
settings.CreateDatabase = true;
settings.DatabaseName = "myDatabase";
});
var app = builder.Build();
app.MapPut("/characters", async (IDocumentStore documentStore) =>
{
var users = new Character[]
{
new() {Id = "characters/joey", Name = "Joey Tribbiani", FavoriteDrink = "Espresso"},
new() {Id = "characters/chandler", Name = "Chandler Bing", FavoriteDrink = "Black Coffee"},
new() {Id = "characters/ross", Name = "Ross Geller", FavoriteDrink = "Macchiato"},
new() {Id = "characters/monica", Name = "Monica Geller", FavoriteDrink = "Latte"},
new() {Id = "characters/phoebe", Name = "Phoebe Buffay-Hannigan", FavoriteDrink = "Herbal Tea"},
new() {Id = "characters/rachel", Name = "Rachel Green", FavoriteDrink = "Cappuccino"}
};
using var session = documentStore.OpenAsyncSession();
foreach (var user in users)
await session.StoreAsync(user);
await session.SaveChangesAsync();
});
app.MapPost("/characters/coffee", async (IDocumentStore documentStore, [FromQuery] string id) =>
{
var now = DateTime.UtcNow;
using var session = documentStore.OpenAsyncSession();
session.TimeSeriesFor(id, "coffee-drinks").Append(now, 1);
session.CountersFor(id).Increment("TotalCups", 1);
await session.SaveChangesAsync();
return Results.Ok($"Logged coffee drink for {id} at {now}");
});
app.MapGet("/characters/coffee-stats", async (IDocumentStore documentStore, [FromQuery] string id) =>
{
using var session = documentStore.OpenAsyncSession();
var coffeeData = await session.TimeSeriesFor(id, "coffee-drinks")
.GetAsync(DateTime.UtcNow.AddDays(-30), DateTime.UtcNow);
var totalCups = await session.CountersFor(id).GetAsync("TotalCups");
return Results.Ok(new { coffeeData, totalCups });
});
app.MapGet("/top-coffee-drinker", (IDocumentStore documentStore) =>
{
using var session = documentStore.OpenSession();
var result = session.Advanced.RawQuery<CounterResult>
("from characters as c where c.\"@metadata\".\"@counters\" == \"TotalCups\" " +
"select { Name: c.Name, TotalCups: counter(c, \"TotalCups\") }")
.ToList()
.OrderByDescending(x => x.TotalCups)
.FirstOrDefault();
return Results.Ok($"The TOP coffee drinker is '{result?.Name}' with {result?.TotalCups} Total Cups!");
});
app.MapDefaultEndpoints();
app.Run();
public class Character
{
public string? Id { get; set; }
public string? Name { get; set; }
public string? FavoriteDrink { get; set; }
}
public class CounterResult
{
public long? TotalCups { get; set; }
public string? Name { get; set; }
}
Great news! We’re all set to go! Let’s run the AppHost project and examine our API service together.
Testing the API with Postman
Once the AppHost and APIService projects run, we can test the API endpoints using Postman.
1. Adding Characters to the Database
- Open Postman.
- Create a new PUT request.
- Set the URL to `http://localhost:5000/characters` (adjust port as needed).
- Send the request.
- Verify that the characters have been successfully stored in RavenDB.
2. Logging Coffee Consumption
- Create a new POST request.
- Set the URL to `http://localhost:5000/characters/coffee?id=characters/joey`.
- Send the request multiple times and with different `id`s to log coffee drinks.
3. Fetching Coffee Stats
- Create a new GET request.
- Set the URL to `http://localhost:5000/characters/coffee-stats?id=characters/joey`.
- Send the request.
- Check the response for Joey’s coffee drinking trends.
4. Finding the Top Coffee Drinker!
- Create a new GET request.
- Set the URL to `http://localhost:5000/top-coffee-drinker`.
- Send the request.
- Verify that the character with the highest coffee consumption is returned (hint: it’s probably Chandler!).
Congratulations! 🎉
You’ve now learned how to integrate .NET Aspire with RavenDB, configure hosting and client integrations, and build an API that efficiently tracks and queries data.
Woah, already finished? 🤯
If you found the article interesting, don’t miss a chance to try our database solution – totally for free!