CouchDB and C#. EFCore-like queries!
Tags: couchdb, csharp, dotnet, aspnetcore
Published: 2021-03-09 21:29:16

---
title: CouchDB and C#. EFCore-like queries!
published: true
description: How to use CouchDB.NET and forget about JSON.
tags: couchdb, csharp, dotnet, aspnetcore
cover_image: https://i.postimg.cc/3Nb98bJQ/couch-wall.png
---

In this post, we'll see how to query `CouchDB` from `C#` using LINQ!

I am going to use my library that after few years, today it reached **v3.0.0**: [CouchDB.NET](https://github.com/matteobortolazzo/couchdb-net).

# What's CouchDB

[Apache CouchDB](https://couchdb.apache.org/) is a distributed document database and its replication protocol is available from servers to mobile phones and web browsers.

It speaks `JSON` natively, and that's great when using `Javascript`, but when using `.NET` it might be painful because of JSON's dynamic nature.

# How CouchDB.NET can help

If you worked with `Entity Framework` before, this library might look familiar.

## The setup
Create your `CouchContext` with the list of databases you have and configure authentication.
> `Rebel` is of type `CouchDocument` as it contains things like Id, Rev, Attachments, and others.

```csharp
public class MyDeathStarContext : CouchContext
{
    public CouchDatabase<Rebel> Rebels { get; set; }

    protected override void OnConfiguring(CouchOptionsBuilder optionsBuilder)
    {
      optionsBuilder
        .UseEndpoint("http://localhost:5984/")
        .EnsureDatabaseExists()
        .UseBasicAuthentication(username: "anakin", password: "empirerule");
    }
}
```

## Use LINQ

The library supports native **.NET LINQ**, ven the SQL-like syntax.

```csharp
await using var context = new MyDeathStarContext();
var skywalkers = await context.Rebels
    .Where(r => 
        r.Surname == "Skywalker" && 
        (
            r.Battles.All(b => b.Planet == "Naboo") ||
            r.Battles.Any(b => b.Planet == "Death Star")
        )
    )
    .OrderByDescending(r => r.Name)
    .ThenByDescending(r => r.Age)
    .Take(2)
    .Select(
        r => r.Name,
        r => r.Age
    })
    .ToListAsync();
```

## What is sent to the database

```json
{
  "selector": {
    "$and": [
      {
        "surname": "Skywalker"
      },
      {
        "$or": [
          {
            "battles": {
              "$allMatch": {
                "planet": "Naboo"
              }
            }
          },
          {
            "battles": {
              "$elemMatch": {
                "planet": "Death Star"
              }
            }
          }
        ]
      }
    ]
  },
  "sort": [
    { "name": "desc" },
    { "age": "desc" }
  ],
  "limit": 2,
  "fields": [
    "name",
    "age"
  ]
}
```

It will automatically optimize the query.

Just to name a few:
* Merge multiple `Where` calls;
* Remove useless condition from the filter (like `Where(r => true || r.Age == 19)`);
* Convert `SingleOrDefault(d => condition)` to `Where(d => condition).Take(2).SingleOrDefault()`;
* Convert `Max(d => d.Property)` to `OrderByDescending(d => d.Property).Take(1).Select(d => d.Property).Max()`

# Other features

In the year, more and more features have been added.

For example:
* Adding/Updating/Deleting documents;
* Adding/Updating/Deleting indexes;
* Database spitting;
* Views;
* Local documents;
* Users management;

# Dependency Injection

If you work with `Asp.NET Core` a [DI package](https://www.nuget.org/packages/CouchDB.NET.DependencyInjection) is available.

It just as easy as register the dependency in the `Startup`:

```csharp
services.AddCouchContext<MyDeathStarContext>(builder => builder
    .UseEndpoint("http://localhost:5984")
    .UseBasicAuthentication(username: "admin", password: "admin"));
```

Then just inject the context:
```csharp
public class RebelsController : Controller
{
    private readonly MyDeathStarContext _context;

    public RebelsController(MyDeathStarContext context)
    {
        _context = context;
    }
}
```

# Finally

If you work with `CouchDB` and `C#` I highly suggest checking the library (even if it might result in more bugs to fix for me).

You can see all that it offers in the [README](https://github.com/matteobortolazzo/couchdb-net) and let me know what you think.