FaunaDB C# Driver
How to Build
Requirements
- .NET SDK
- Mono if you're using macOS or Linux
Build
Running the following command will build the driver for all supported .NET frameworks:
dotnet build FaunaDB.Client
If you're using MacOS or Linux you may need to override FrameworkPathOverride
to point to the Mono specific api:
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
dotnet test FaunaDB.Client.Test
If you're using macOS or Linux you may need to override FrameworkPathOverride
:
FrameworkPathOverride=/Library/Frameworks/Mono.framework/Versions/Current/lib/mono/4.5-api dotnet test FaunaDB.Client.Test/ --framework net45
specific tests:
FrameworkPathOverride=/Library/Frameworks/Mono.framework/Versions/Current/lib/mono/4.5-api dotnet test FaunaDB.Client.Test/ --framework net45 --filter Name~EncoderTest
Referencing FaunaDB Assembly
First install the Nuget package by adding the package reference to your MSBuild project:
<PackageReference Include="FaunaDB.Client" Version="3.0.0" />
or by using your IDE and searching for FaunaDB.Client
.
Quickstart
Here is an example on how to execute a simple query on FaunaDB:
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 = "<<YOUR-SECRET-HERE>>";
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<Value[]> data = result.At("data").To<Value[]>();
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.
FaunaClient
How to instantiate a FaunaDB 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:
// 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);
How to execute a query
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:
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.
IResult<Value[]> data = result.At("data").To<Value[]>();
IResult<T>
objects
How work with 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.
data.Match(
Success: value => ProcessData(value),
Failure: reason => Console.WriteLine($"Something went wrong: {reason}")
);
Optionally it's possible transform one IResult<T>
into another IResult<U>
of different type using Map
and FlatMap
.
IResult<int> result = <<...>>;
IResult<string> 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:
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:
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
:
Value value = await client.Query(Get(Ref(Collection("product"), "123456789")));
Product product = Decoder.Decode<Product>(value.At("data"));
or via the To<T>()
helper method:
Value value = await client.Query(Get(Ref(Collection("product"), "123456789")));
IResult<Product> product = value.At("data").To<Product>();
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<Product>().Value;
Console.WriteLine("Product loaded: {0}", prod.Description);
Note that in this case the return type is IResult<T>
.
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<T>
, and their respective interfaces such asIList<T>
. - Dictionaries with string keys, such as
Dictionary<string, T>
and its respective interfaceIDictionary<string, T>
.
License
Copyright 2018 Fauna, Inc.
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
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.