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

https://github.com/coronabytes/dotnet-arangodb-extensions

Serilog, DevExtreme and DataProtection extensions for .NET ArangoDB driver
https://github.com/coronabytes/dotnet-arangodb-extensions

arangodb arangodb-client aspnetcore dataprotection devextreme-query netcore serilog serilog-sink

Last synced: 6 months ago
JSON representation

Serilog, DevExtreme and DataProtection extensions for .NET ArangoDB driver

Awesome Lists containing this project

README

        

[![Build](https://github.com/coronabytes/dotnet-arangodb-extensions/actions/workflows/build.yml/badge.svg)](https://github.com/coronabytes/dotnet-arangodb-extensions/actions/workflows/build.yml)

# Extensions for .NET ArangoDB Driver
See [dotnet-arangodb](https://github.com/coronabytes/dotnet-arangodb)

| Extension | Nuget | Command |
| :--- | :--- | :--- |
| [Core.Arango.Migration](https://www.nuget.org/packages/Core.Arango.Migration) | ![Nuget](https://img.shields.io/nuget/v/Core.Arango.Migration) ![Nuget](https://img.shields.io/nuget/dt/Core.Arango.Migration) | dotnet add package Core.Arango.Migration |
| [Core.Arango.DataProtection](https://www.nuget.org/packages/Core.Arango.DataProtection) | ![Nuget](https://img.shields.io/nuget/v/Core.Arango.DataProtection) ![Nuget](https://img.shields.io/nuget/dt/Core.Arango.DataProtection) | dotnet add package Core.Arango.DataProtection |
| [Core.Arango.DevExtreme](https://www.nuget.org/packages/Core.Arango.DevExtreme) | ![Nuget](https://img.shields.io/nuget/v/Core.Arango.DevExtreme) ![Nuget](https://img.shields.io/nuget/dt/Core.Arango.DevExtreme) | dotnet add package Core.Arango.DevExtreme |
| [Core.Arango.Serilog](https://www.nuget.org/packages/Core.Arango.Serilog) | ![Nuget](https://img.shields.io/nuget/v/Core.Arango.Serilog) ![Nuget](https://img.shields.io/nuget/dt/Core.Arango.Serilog) | dotnet add package Core.Arango.Serilog |

# Migration
- Ensures the Arango structure / model is up-to-date
- Synchronises collection, index, graph, analyzer, views and custom functions from code model to arango db
- objects are compared and if they differ they will be dropped and recreated
- objects cannot be renamed with this method as they are matched by name and not by id
- collections cannot be updated (data-loss) with this method, only new ones can be created and old ones dropped
- Database export and import support with zip-archives
- Full and partial updates
- Optional history collection for advanced migration scenarios, like running transformation queries
- Still under heavy development, might toss some functions around

## Extract structure to code model
```csharp
var migrationService = new ArangoMigrator(Arango);

var structure = await migrationService.GetStructureAsync("source-database");
```

## Apply structure from code model (dry run)
```csharp
var migrationService = new ArangoMigrator(Arango);

await migrationService.ApplyStructureAsync("target-database", structure, new ArangoMigrationOptions
{
DryRun = true,
Notify = n =>
{
if (n.State != ArangoMigrationState.Identical)
_output.WriteLine($"{n.State} {n.Object} {n.Name}");
}
});
```

## Apply structure from code model
```csharp
var migrationService = new ArangoMigrator(Arango);

await migrationService.ApplyStructureAsync("target-database", new ArangoStructure
{
Collections = new List
{
new ()
{
Collection = new ArangoCollection
{
Name = "Project",
Type = ArangoCollectionType.Document
},
Indices = new List
{
new ()
{
Name = "IDX_ParentKey",
Fields = new List {"ParentKey"},
Type = ArangoIndexType.Hash
}
}
},
new ()
{
Collection = new ArangoCollection
{
Name = "Activity",
Type = ArangoCollectionType.Document
},
Indices = new List
{
new ()
{
Name = "IDX_ProjectKey",
Fields = new List {"ProjectKey"},
Type = ArangoIndexType.Hash
}
}
}
}
});
```

## Export database with structure and data to zip archive
```csharp
var migrationService = new ArangoMigrator(Arango);

await using var fs = File.Create("export.zip", 1024 * 1024);
await migrationService.ExportAsync("source-database", fs, ArangoMigrationScope.Data | ArangoMigrationScope.Structure);
```

## Import database with structure and data from zip archive
```csharp
var migrationService = new ArangoMigrator(Arango);

await using var fs = File.OpenRead("export.zip");
await migrationService.ImportAsync("target-database", fs, ArangoMigrationScope.Data | ArangoMigrationScope.Structure);
```

## Advanced migrations with history collection
```csharp
var migrator = new ArangoMigrator(Arango);
migrator.HistoryCollection = "MigrationHistory";

// load all migrations from assembly
migrator.AddMigrations(typeof(Program).Assembly);

// apply all migrations up to latest
await migrator.UpgradeAsync("target-database");

// sample migration / downgrades not yet supported
public class M20210401_001 : IArangoMigration
{
public long Id => 20210401_001; // sortable unique id
public string Name => "Initial";

public async Task Up(IArangoMigrator migrator, ArangoHandle handle)
{
await migrator.ApplyStructureAsync(...);
await migrator.Context.Query.ExecuteAsync(...);
}

public Task Down(IArangoMigrator migrator, ArangoHandle handle)
{
throw new NotImplementedException();
}
}
```

# DataProtection
```csharp
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton(new ArangoContext(Configuration.GetConnectionString("Arango")));

var dataProtection = services.AddDataProtection()
.SetApplicationName("App")
.SetDefaultKeyLifetime(TimeSpan.FromDays(30));
dataProtection.PersistKeysToArangoDB(database: "dataprotection", collection: "keys");
}
```

# DevExtreme
- Translates DevExtreme queries to AQL with filtering, sorting, grouping and summaries on a 'best effort basis'
- Parameters are escaped with bindvars
- Property names
- need to match ^[A-Za-z_][A-Za-z0-9\\.]*$
- need to be within 128 characters
- can be customized with ValidPropertyName() and PropertyTransform()
- Developer retains full control over the projection - full document by default
- Check safety limits in settings if your query fails
- Support for ArangoSearch is coming soon
- Not so soon...
- Groupings by foreign key can be enriched with displayValue using GroupLookups()
```csharp

private static readonly ArangoTransformSettings Transform = new ArangoTransformSettings
{
IteratorVar = "x",
Key = "key",
Filter = "x.Active == true",
RestrictGroups = new HashSet
{
"ProjectKey", "UserKey"
}, // null allows all groupings (not recommended) / empty hashset disables grouping
GroupLookups = new Dictionary
{
["ProjectKey"] = "DOCUMENT(AProject, ProjectKey).Name",
["UserKey"] = "DOCUMENT(AUser, UserKey).Name"
}
};

[HttpGet("dx-query")]
public async Task> DxQuery([FromQuery] DataSourceLoadOptions loadOptions)
{
var arangoTransform = new ArangoTransform(loadOptions, Transform);

if (!arangoTransform.Transform(out var error))
return BadRequest(error);

return await arangoTransform.ExecuteAsync(arango, "database", "collection");
}
```

# Serilog
```csharp
builder.Host.UseSerilog(
(c, log) =>
{
var arango = builder.Configuration.GetConnectionString("Arango");

log.Enrich.FromLogContext();
log.WriteTo.Console(theme: AnsiConsoleTheme.Code);
log.WriteTo.Sink(new PeriodicBatchingSink(new ArangoSerilogSink(new ArangoContext(arango)), new PeriodicBatchingSinkOptions
{
BatchSizeLimit = 1000,
QueueLimit = 100000,
Period = TimeSpan.FromSeconds(2),
EagerlyEmitFirstEvent = true
}));
});
```