Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/fauna/faunadb-csharp

C# driver for FaunaDB v4
https://github.com/fauna/faunadb-csharp

client clients csharp database driver drivers fauna faunadb

Last synced: 3 days ago
JSON representation

C# driver for FaunaDB v4

Awesome Lists containing this project

README

        

# C# driver for Fauna v4 (deprecated)

[![NuGet](https://img.shields.io/nuget/v/FaunaDB.Client.svg?maxAge=21600)](https://www.nuget.org/packages/FaunaDB.Client/)
[![License](https://img.shields.io/badge/license-MPL_2.0-blue.svg?maxAge=2592000)](https://raw.githubusercontent.com/fauna/faunadb-csharp/main/LICENSE)

> [!WARNING]
> Fauna is decommissioning FQL v4 on June 30, 2025.
>
> This driver is not compatible with FQL v10, the latest version. Fauna accounts
> created after August 21, 2024 must use FQL v10. Ensure you migrate existing
> projects to the official v10 driver by the v4 EOL date:
> https://github.com/fauna/fauna-dotnet.
>
> For more information, see the [v4 end of life (EOL)
> announcement](https://docs.fauna.com/fauna/v4/#fql-v4-end-of-life) and
> [related FAQ](https://docs.fauna.com/fauna/v4/migration/faq).

The official C# driver for [Fauna v4](https://docs.fauna.com/fauna/v4/).

See the [Fauna v4 documentation](https://docs.fauna.com/fauna/v4) and
[tutorials](https://docs.fauna.com/fauna/v4/learn/tutorials/fql/crud?lang=javascript) for
guides and a complete database [API
reference](https://docs.fauna.com/fauna/v4/api/fql/).

## Documentation

C# doc are hosted on GitHub:

* [faunadb-csharp](https://fauna.github.io/faunadb-csharp/4.2.0/)

## How to Build

### Requirements

* [.NET SDK](https://www.microsoft.com/net/download/all)
* Mono if you're using macOS or Linux

### Build

Running the following command will build the driver for all supported .NET frameworks:

```bash
dotnet build FaunaDB.Client
```

If you're using MacOS or Linux you may need to override `FrameworkPathOverride` to point to the Mono specific api:

```bash
FrameworkPathOverride=/Library/Frameworks/Mono.framework/Versions/Current/lib/mono/4.5-api dotnet build FaunaDB.Client/ --framework net45
```

### Running Tests

Running the following command will run the tests for all supported .NET frameworks

```bash
dotnet test FaunaDB.Client.Test
```

If you're using macOS or Linux you may need to override `FrameworkPathOverride`:

```bash
FrameworkPathOverride=/Library/Frameworks/Mono.framework/Versions/Current/lib/mono/4.5-api dotnet test FaunaDB.Client.Test/ --framework net45
```

specific tests:

```bash
FrameworkPathOverride=/Library/Frameworks/Mono.framework/Versions/Current/lib/mono/4.5-api dotnet test FaunaDB.Client.Test/ --framework net45 --filter Name~EncoderTest
```

If you're using .net core (which is cross-platform for Windows, Mac or Linux), use the following examples for running tests:
```bash
# runs all the tests for all target frameworks from csproj file
dotnet test FaunaDB.Client.Test

# runs tests for a specific target framework
dotnet test FaunaDB.Client.Test --framework net45
dotnet test FaunaDB.Client.Test --framework netcoreapp3.1
dotnet test FaunaDB.Client.Test --framework net5.0

# runs all the tests in a specified test class (format: namespace.class)
dotnet test FaunaDB.Client.Test --filter FullyQualifiedName~Test.EnvironmentHeaderTest --framework netcoreapp3.1

# runs a single test
dotnet test FaunaDB.Client.Test --filter Name=TestNetlifyEnvironment --framework netcoreapp3.1

# runs all the tests starting with TestUnknownEnvironment
dotnet test FaunaDB.Client.Test --filter FullyQualifiedName~Test.EnvironmentHeaderTest.TestUnknownEnvironment --framework netcoreapp3.1
```

## Referencing FaunaDB Assembly

First install the Nuget package by adding the package reference to your MSBuild project:

```xml

```

or by using your IDE and searching for `FaunaDB.Client`.

## Quickstart

Here is an example on how to execute a simple query on FaunaDB:

```csharp
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using FaunaDB.Client;
using FaunaDB.Types;

using static FaunaDB.Query.Language;

namespace FaunaDBProject
{
class FaunaDBHelloWorld
{
static readonly string ENDPOINT = "https://db.fauna.com:443";
static readonly string SECRET = "<>";

static void ProcessData(Value[] values)
{
foreach (Value value in values)
{
//do something
}
}
static async Task DoQuery(FaunaClient client)
{
Value result = await client.Query(Paginate(Match(Index("spells"))));
IResult data = result.At("data").To();

data.Match(
Success: value => ProcessData(value),
Failure: reason => Console.WriteLine($"Something went wrong: {reason}")
);
}

public static void Main(string[] args)
{
var client = new FaunaClient(endpoint: ENDPOINT, secret: SECRET);

DoQuery(client).Wait();
}
}
}
```

This small example shows how to use pretty much every aspect of the library.

#### How to instantiate a FaunaDB `FaunaClient`

```csharp
var client = new FaunaClient(endpoint: ENDPOINT, secret: SECRET, httpClient: HTTP_CLIENT, timeout: TIMEOUT);
```

Except `secret` all other arguments are optional.

You can also pass a custom HttpClient when creating a new FaunaClient:

```csharp
// using System.Net.Http;
var http = new HttpClient();

// The default request headers can be any string values, but should be specific to your application.
http.DefaultRequestHeaders.Add("X-Custom-Header", "42");

http.Timeout = TimeSpan.FromSeconds(15);

var client = new FaunaClient("secret", "http://localhost:9090/", httpClient: http);
```

#### HTTP 2.0 support
Starting from version 4.0.0 of this driver (faunadb-csharp), HTTP/2 support is enabled by default for .NET standards 2.1 and above.
This means that if you use .NET core 3.1 and above (which support that standard), you'll be sending requests to Fauna on HTTP/2.
.NET standards lower than 2.1 and .NET frameworks 4.5-4.8 have HTTP/1.1 enabled as the default protocol version, since they lack of support for HTTP/2.
We've also added an optional parameter if you want to specify the version of the protocol directly:
```csharp
var adminClient = new FaunaClient(
endpoint: endpoint,
secret: secret,
httpVersion: HttpVersion.Version11
);
```

#### How to execute a query

```csharp
Value result = await client.Query(Paginate(Match(Index("spells"))));
```

`Query` methods receives an `Expr` object. `Expr` objects can be composed with others `Expr` to create complex query objects. `FaunaDB.Query.Language` is a helper class where you can find all available expressions in the library.

You can also pass a `TimeSpan queryTimeout` argument to that specific query as well:

```csharp
Value result = await client.Query(Paginate(Match(Index("spells"))), TimeSpan.FromSeconds(42));
```

#### How to access objects fields and convert to primitive values

Objects fields are accessed through `At` methods of `Value` class. It's possible to access fields by names if the value represents an object or by index if it represents an array. Also it's possible to convert `Value` class to its primitive correspondent using `To` methods specifying a type.

```csharp
IResult data = result.At("data").To();
```

#### How work with `IResult` objects

This object represents the result of an operation and it might be success or a failure. All convertion operations returns an object like this. This way it's possible to avoid check for nullability everywhere in the code.

```csharp
data.Match(
Success: value => ProcessData(value),
Failure: reason => Console.WriteLine($"Something went wrong: {reason}")
);
```

Optionally it's possible transform one `IResult` into another `IResult` of different type using `Map` and `FlatMap`.

```csharp
IResult result = <<...>>;
IResult result.Map(value => value.toString());
```

If `result` represents an failure all calls to `Map` and `FlatMap` are ignored. See `FaunaDB.Types.Result`.

### How to work with user defined classes

Instead of manually creating your objects via the DSL (e.g. the Obj() method), you may use the `Encoder` class to convert a user-defined type into the equivalent `Value` type.

For example:

```csharp
class Product
{
[FaunaField("description")]
public string Description { get; set; }

[FaunaField("price")]
public double Price { get; set; }

[FaunaConstructor]
public Product(string description, double price)
{
Description = description;
Price = price;
}
}
```

To persist an instance of `Product` in FaunaDB:

```csharp
Product product = new Product("Smartphone", 649.90);

await client.Query(
Create(
Collection("product"),
Obj("data", Encoder.Encode(product))
)
);
```

To convert from a `Value` type back to the `Product` type, you can use a `Decoder`:

```csharp
Value value = await client.Query(Get(Ref(Collection("product"), "123456789")));

Product product = Decoder.Decode(value.At("data"));
```

or via the `To()` helper method:

```csharp
Value value = await client.Query(Get(Ref(Collection("product"), "123456789")));

IResult product = value.At("data").To();
product.Match(
Success: p => Console.WriteLine("Product loaded: {0}", p.Description),
Failure: reason => Console.WriteLine($"Something went wrong: {reason}")
);

// or even:

Product productLoaded = value.At("data").To().Value;
Console.WriteLine("Product loaded: {0}", prod.Description);
```

Note that in this case the return type is `IResult`.

There are three attributes that can be used to change the behavior of the `Encoder` and `Decoder`:

- `FaunaField`: Used to override a custom field name and/or provide a default value for that field. If this attribute is not specified, the member name will be used instead. Can be used on fields, properties and constructor arguments.
- `FaunaConstructor`: Used to mark a constructor or a public static method as the method used to instantiate the specified type. This attribute can be used only once per class.
- `FaunaIgnore`: Used to ignore a specific member. Can be used on fields, properties and constructors arguments. If used on a constructor argument, that argument must have a default value.

`Encoder` and `Decoder` can currently convert:

- Primitive scalar types (`int`, `long`, `string`, etc.)
- Primitive arrays, generic collections such as `List`, and their respective interfaces such as `IList`.
- Dictionaries with string keys, such as `Dictionary` and its respective interface `IDictionary`.

### Document streaming

Fauna supports document streaming, where changes to a streamed document are pushed to all clients subscribing to that document.

The streaming API is built using the Observer pattern which enables a subscriber to register with and receive notifications from a provider.
Provider is implemented within `StreamingEventHandler` class, and subscriber within `StreamingEventMonitor` class.

The following example assumes that you have already created a `FaunaClient`.

In the example below, we are capturing the 4 first messages by manually binding a subscriber.

```csharp
// docRef is a reference to the document for which we want to stream updates.
// You can acquire a document reference with a query like the following, but it
// needs to work with the documents that you have.
// var docRef = Get(Ref(Collection("scoreboards"), "123"));

// create a data provider
var provider = await adminClient.Stream(docRef);

// we use this object to signalize a completion of
// asynchronous operation for the current example
var done = new TaskCompletionSource();

// a collection for storage of incoming events from the provider
List events = new List();

// creating a subscriber
// it takes 3 lambdas that describe the following:
// - next event processing
// - error processing
// - completion processing
var monitor = new StreamingEventMonitor(
value =>
{
events.Add(value);
if (events.Count == 4)
{
provider.Complete();
}
else
{
provider.RequestData();
}
},
ex => { done.SetException(ex); },
() => { done.SetResult(null); }
);

// subscribe to data provider
monitor.Subscribe(provider);

// blocking until we receive all the events
await done.Task;

// clear the subscription
monitor.Unsubscribe();
```

You can also extend a base class instead of passing lambdas:
```csharp
private class MyStreamingMonitor : StreamingEventMonitor
{
// optionally override OnNext event
public override void OnNext(Value value)
{
// process your event
RequestData();
}

// optionally override OnError event
public override void OnError(Exception error)
{
// process an error
}

// optionally override OnCompleted event
public override void OnCompleted()
{
// process completion event
}
}

// creating a subscriber
var monitor = new MyStreamingMonitor();

// subscribe to data provider
monitor.Subscribe(provider);

// clear the subscription
monitor.Unsubscribe();
```

## License

Copyright 2021 [Fauna, Inc.](https://fauna.com/)

Licensed under the Mozilla Public License, Version 2.0 (the "License"); you may
not use this software except in compliance with the License. You may obtain a
copy of the License at

[http://mozilla.org/MPL/2.0/](http://mozilla.org/MPL/2.0/)

Unless required by applicable law or agreed to in writing, software distributed
under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied. See the License for the
specific language governing permissions and limitations under the License.