Getting Started with C# and InfluxDB

Navigate to:

This post was written by James Hickey. Scroll below for full bio and picture following this article. 

Time series databases (TSDBs) can transform the way you handle streams of data in real time or IoT applications. In this tutorial, you’ll learn how to set one up in a C# application.

Relational databases have their place. They’re great at things like data normalization, avoiding duplication, indexing over specific data points (like columns), and handling atomic changes to the schema.

But when it comes to storing, manipulating, and querying against large data sets focused on time stamps or time-based queries, TSDBs shine — with InfluxDB being the most popular.

You need a TSDB to consume tons of time-based data. This includes sensor data, server metrics, application events, network data, general IoT data, or just time-based data generated by your business domain. TSDBs are optimized not only for writing tons of time-stamped data efficiently, but they can also run complex, time-based queries in milliseconds.

In this article, you’ll learn how to get started with InfluxDB and C#. You’ll learn how to configure InfluxDB on your PC, connect it to a .NET application, and read/write some data to InfluxDB.

To see all the code first, take a look at the sample code from this GitHub repository.

Let’s get started!

Installing InfluxDB using Docker

Before you move forward, make sure you have Docker installed.

Next, execute the following Docker command from a terminal:

docker pull influxdb:2.0.7

Note: Version 2.0.7 is currently the latest version of InfluxDB. See InfluxDB’s documentation for the most up-to-date docker pull command available.

Run a new run-instance of InfluxDB using this command:

docker run --name influxdb -p 8086:8086 influxdb:2.0.7

Next, navigate to http://localhost:8086/ on your local machine. Click Get Started and fill in the following values:

  • User: admin
  • Password: adminadmin
  • Organization: organization
  • Bucket: bucket

Next, navigate to the InfluxDB sign-in page at http://localhost:8086/.

Create a new bucket by clicking on Data, then Buckets. Click Create Bucket, and name it test-bucket. This will create an empty bucket to write your data to.

InfluxDB create bucket

You’ll need to capture your user’s authentication token. After signing in, click on Data, then Tokens, and select admin’s Token.

InfluxDB load data tokens

Copy the token that is displayed — you’ll need it soon.

Creating a .NET console application

You’ll be creating an MVC .NET web application that will interact with InfluxDB. Let’s create it by running this command in your terminal:

dotnet new mvc -o app

Note: If you don’t have the .NET CLI installed, you can download the latest .NET SDK here.

Next, cd app into the MVC application folder. Then, install the InfluxDB C# SDK by executing this in your terminal:

dotnet add package InfluxDB.Client

You’ll also need the Coravel package to schedule background jobs easily:

dotnet add package Coravel

Building the InfluxDB application service

Open up appsettings.json and replace it with the following:

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*",

  "InfluxDB": {
    "Token": "Your_Token_Goes_Here"
  }
}

Next, create a new file — Services/InfluxDBService.cs — and replace its contents with the following:

using System;
using System.Threading.Tasks;
using InfluxDB.Client;
using Microsoft.Extensions.Configuration;

namespace app.Services
{
    public class InfluxDBService
    {
        private readonly string _token;

        public InfluxDBService(IConfiguration configuration)
        {
            _token = configuration.GetValue<string>("InfluxDB:Token");
        }

        public void Write(Action<WriteApi> action)
        {
            using var client = InfluxDBClientFactory.Create("http://localhost:8086", _token);
            using var write = client.GetWriteApi();
            action(write);
        }

        public async Task<T> QueryAsync<T>(Func<QueryApi, Task<T>> action)
        {
            using var client = InfluxDBClientFactory.Create("http://localhost:8086", _token);
            var query = client.GetQueryApi();
            return await action(query);
        }
    }
}

Using common .NET and C# conventions, this wrapper class will allow you to use the InfluxDB C# client in a reliable way; it will be properly disposed of when no longer needed.

Your token is grabbed from the appsettings.json file by the IConfiguration service. There are two convenience methods: one to write and one to read from InfluxDB.

In Startup.cs in the ConfigureServices() method, add the following lines:

services.AddSingleton<InfluxDBService>();

You’ll also have to add the namespace reference to the top of the file:

using app.Services;

Now your service will be available from .NET’s built-in dependency injection providers.

Writing to InfluxDB

Now, let’s simulate an airplane sending its current altitude back to a central location every five seconds. To get started, you’ll be using Coravel’s task scheduler.

Open up Startup.cs again, and add the following references to the top of the file:

using Coravel;
using app.Invocables; // You'll create this namespace soon :)

Next, add the following line to the ConfigureServices method:

// You'll create this class soon :)
services.AddTransient<WriteRandomPlaneAltitudeInvocable>();
services.AddScheduler();

Then, add the following lines to the end of the Configure method:

app.ApplicationServices.UseScheduler(scheduler =>
{
    scheduler
        .Schedule<WriteRandomPlaneAltitudeInvocable>()
        .EveryFiveSeconds();
});

Now, create a file named Invocables/WriteRandomPlaneAltitudeInvocable.cs. Replace its contents with the following:

using System;
using System.Threading.Tasks;
using app.Services;
using Coravel.Invocable;
using InfluxDB.Client.Api.Domain;
using InfluxDB.Client.Writes;

namespace app.Invocables
{
    public class WriteRandomPlaneAltitudeInvocable : IInvocable
    {
        private readonly InfluxDBService _service;
        private static readonly Random _random = new Random();

        public WriteRandomPlaneAltitudeInvocable(InfluxDBService service)
        {
            _service = service;
        }

        public Task Invoke()
        {
            _service.Write(write =>
            {
                var point = PointData.Measurement("altitude")
                    .Tag("plane", "test-plane")
                    .Field("value", _random.Next(1000, 5000))
                    .Timestamp(DateTime.UtcNow, WritePrecision.Ns);

                write.WritePoint("test-bucket", "organization", point);
            });

            return Task.CompletedTask;
        }
    }
}

This class is scheduled to execute every five seconds. Again, it’s simulating an airplane sending its current altitude back to a central location for data storage and reporting.

Reading from InfluxDB

When you run the application it will write a random altitude every five seconds, and you need to see those values.

First, let’s create a model that a controller will pass to its view. Create the file Models/AltitudeModel.cs, and replace it with the following:

namespace app.Models
{
    public class AltitudeModel
    {
        public string Time { get; init; }
        public int Altitude { get; init; }
        public string DisplayText => $"Plane was at altitude {Altitude} ft. at {Time}.";
    }
}

Next, open up Controllers/HomeController.cs, and replace the Index method with the following:

public async Task<IActionResult> Index([FromServices] InfluxDBService service)
{
    var results = await service.QueryAsync(async query =>
    {
        var flux = "from(bucket:\"test-bucket\") |> range(start: 0)";
        var tables = await query.QueryAsync(flux, "organization");
        return tables.SelectMany(table =>
            table.Records.Select(record =>
                new AltitudeModel
                {
                    Time = record.GetTime().ToString(),
                    Altitude = int.Parse(record.GetValue().ToString())
                }));
    });

    return View(results);
}

Don’t forget to add the required references to the top of the file:

using app.Models;
using app.Services;

Next, open up Views/Home/Index.cshtml, and replace it with the following:

@model IEnumerable<app.Models.AltitudeModel>

@{
    ViewData["Title"] = "Home Page";
}

<ul>
    @foreach (var record in Model)
    {
        <li>@record.DisplayText</li>
    }
</ul>

Now, run the application by executing dotnet run in a terminal. After every five seconds, you should see a new value written when you refresh the page.

application results screenshot

Using Flux to filter your queries

To demonstrate how easy it is to perform more complex queries against your data, open up Controllers/HomeController.cs again. In the Index method, replace the Flux query you already have with the following lines:

var flux = "from(bucket:\"test-bucket\") " +
           "|> range(start: 0) " +
           "|> filter(fn: (r) => " +
           "r._measurement == \"altitude\" and " +
           "r._value > 3500)";

Run the application again. You’ll see that the only pieces of data displayed are those with an altitude above 3500 feet.

Take a look at the Flux docs to perform more advanced queries like calculating sums, grouping data, getting averages, and more.

Conclusion

In this article, you learned how to install and configure InfluxDB on your local machine, create a new .NET web application, and read/write to InfluxDB. You also learned how to collect and view data from a source that periodically sends its current state to be stored at a specific point in time.

By using InfluxDB’s Flux query language or the SQL-like InfluxQL query language, you can data crunch using more advanced queries like the C# client.

Next time you collect data that needs to be queried and aggregated based on its time stamp, take a look at InfluxDB and the various programming language SDKs available.

About the author:

james hickey

James is a Microsoft MVP with a background building web and mobile applications in fintech and insurance industries. He’s the author of “Refactoring TypeScript” and creator of open-source tools for .NET called Coravel. He lives in Canada, just ten minutes from the highest tides in the world.