Files
mixtape/zero.Core/Stores/EntityStore.cs
T

186 lines
5.9 KiB
C#
Raw Normal View History

2021-11-23 11:35:01 +01:00
using FluentValidation.Results;
2021-11-18 16:00:20 +01:00
using Raven.Client.Documents.Indexes;
using Raven.Client.Documents.Linq;
2021-11-23 22:56:22 +01:00
namespace zero.Stores;
2021-11-19 12:03:36 +01:00
2021-12-29 15:29:33 +01:00
public abstract class EntityStore<T> : IEntityStore<T> where T : ZeroIdEntity, ISupportsFlavors, ISupportsSorting, new()
2021-11-18 16:00:20 +01:00
{
/// <inheritdoc />
public Guid Guid { get; private set; } = Guid.NewGuid();
/// <inheritdoc />
2021-12-28 11:33:41 +01:00
public IZeroDocumentSession Session => Operations.Session;
2021-11-18 16:00:20 +01:00
/// <inheritdoc />
public StoreConfig Config => Operations.Config;
2021-11-18 16:00:20 +01:00
protected IZeroContext Context { get; private set; }
2021-11-23 11:35:01 +01:00
protected IInterceptors Interceptors { get; private set; }
2021-11-23 22:56:22 +01:00
protected IStoreOperations Operations { get; private set; }
2021-11-18 16:00:20 +01:00
2021-11-24 13:56:08 +01:00
protected IZeroOptions Options { get; private set; }
2021-11-18 16:00:20 +01:00
2021-11-23 22:56:22 +01:00
public EntityStore(IStoreContext collectionContext)
2021-11-18 16:00:20 +01:00
{
2021-11-19 13:31:54 +01:00
Context = collectionContext.Context;
Interceptors = collectionContext.Interceptors;
2021-11-24 13:56:08 +01:00
Options = collectionContext.Options;
2021-12-28 11:33:41 +01:00
Operations = new StoreOperations(collectionContext);
2021-11-18 16:00:20 +01:00
}
2021-11-23 11:35:01 +01:00
/// <inheritdoc />
2021-12-03 14:45:49 +01:00
public virtual Task<T> Empty(string flavorAlias = null) => Operations.Empty<T>(flavorAlias);
2021-11-19 13:31:54 +01:00
2021-12-02 13:43:04 +01:00
/// <inheritdoc />
2021-12-03 14:45:49 +01:00
public virtual Task<TFlavor> Empty<TFlavor>(string flavorAlias = null) where TFlavor : T, new() => Operations.Empty<T, TFlavor>(flavorAlias);
2021-12-02 13:43:04 +01:00
2021-11-23 11:35:01 +01:00
/// <inheritdoc />
public virtual Task<T> Load(string id, string changeVector = null) => Operations.Load<T>(id, changeVector);
/// <inheritdoc />
public virtual Task<Dictionary<string, T>> Load(IEnumerable<string> ids) => Operations.Load<T>(ids);
/// <inheritdoc />
2021-11-23 15:43:21 +01:00
public virtual Task<Paged<T>> Load(int pageNumber, int pageSize, Func<IRavenQueryable<T>, IQueryable<T>> querySelector = default) => Operations.Load(pageNumber, pageSize, querySelector);
2021-11-23 11:35:01 +01:00
/// <inheritdoc />
2021-11-23 15:43:21 +01:00
public virtual Task<Paged<T>> Load<TIndex>(int pageNumber, int pageSize, Func<IRavenQueryable<T>, IQueryable<T>> querySelector = default) where TIndex : AbstractCommonApiForIndexes, new() => Operations.Load<T, TIndex>(pageNumber, pageSize, querySelector);
2021-11-23 11:35:01 +01:00
/// <inheritdoc />
public virtual Task<List<T>> LoadAll() => Operations.LoadAll<T>();
/// <inheritdoc />
2021-11-23 15:43:21 +01:00
public virtual IAsyncEnumerable<T> Stream(Func<IRavenQueryable<T>, IQueryable<T>> expression) => Operations.Stream<T>(expression);
2021-11-23 11:35:01 +01:00
/// <inheritdoc />
2021-12-12 15:41:51 +01:00
public virtual string GetChangeToken(T model) => Operations.GetChangeToken(model);
2021-11-23 11:35:01 +01:00
/// <inheritdoc />
2021-11-26 15:47:11 +01:00
public virtual Task<Result<T>> Create(T model) => Operations.Create(model, async m => await Validate(m));
2021-11-23 15:43:21 +01:00
/// <inheritdoc />
2021-11-26 15:47:11 +01:00
public virtual Task<Result<T>> Update(T model) => Operations.Update(model, async m => await Validate(m));
2021-11-23 11:35:01 +01:00
2021-12-29 15:29:33 +01:00
/// <inheritdoc />
public virtual Task<Result<IOrderedEnumerable<T>>> Sort(string[] sortedIds) => Operations.Sort<T>(sortedIds);
2021-11-23 11:35:01 +01:00
/// <inheritdoc />
2021-11-26 15:47:11 +01:00
public virtual Task<Result<T>> Delete(T model) => Operations.Delete(model);
2021-11-23 11:35:01 +01:00
2021-11-18 16:00:20 +01:00
/// <inheritdoc />
public virtual async Task<ValidationResult> Validate(T model)
{
ZeroValidator<T> validator = new();
ValidationRules(validator);
return await validator.ValidateAsync(model);
}
2021-11-19 12:03:36 +01:00
/// <summary>
/// Create rules for validation
/// </summary>
protected virtual void ValidationRules(ZeroValidator<T> validator) { }
2021-11-18 16:00:20 +01:00
/// <summary>
/// Do only return the model when it is set to active or inactive entities are included with IncludeInactive()
/// </summary>
2021-11-24 15:49:25 +01:00
protected virtual T WhenActive(T model) => model != null && (Config.IncludeInactive || (model is not ZeroEntity || (model as ZeroEntity).IsActive)) ? model : default;
2021-11-18 16:00:20 +01:00
}
2021-12-29 15:29:33 +01:00
public interface IEntityStore<T> where T : ZeroIdEntity, ISupportsFlavors, ISupportsSorting, new()
2021-11-18 16:00:20 +01:00
{
2021-11-24 13:56:08 +01:00
/// <summary>
/// Id for this store
/// </summary>
Guid Guid { get; }
/// <summary>
/// Access the current document session
/// </summary>
IZeroDocumentSession Session { get; }
/// <summary>
/// Configure the store
/// </summary>
StoreConfig Config { get; }
2021-11-19 13:31:54 +01:00
/// <summary>
2021-12-02 16:06:34 +01:00
/// Get new instance of an entity (with an optional flavor)
2021-11-19 13:31:54 +01:00
/// </summary>
2021-12-03 14:45:49 +01:00
Task<T> Empty(string flavorAlias = null);
2021-11-19 13:31:54 +01:00
2021-12-02 13:43:04 +01:00
/// <summary>
/// Get new instance of an entity with a specific flavor
/// </summary>
2021-12-03 14:45:49 +01:00
Task<TFlavor> Empty<TFlavor>(string flavorAlias = null) where TFlavor : T, new();
2021-12-02 13:43:04 +01:00
2021-11-18 16:00:20 +01:00
/// <summary>
/// Get an entity by Id
/// </summary>
Task<T> Load(string id, string changeVector = null);
/// <summary>
/// Get entities by ids
/// </summary>
2021-11-19 13:31:54 +01:00
Task<Dictionary<string, T>> Load(IEnumerable<string> ids);
2021-11-18 16:00:20 +01:00
/// <summary>
/// Get entities by query
/// </summary>
2021-11-23 15:43:21 +01:00
Task<Paged<T>> Load(int pageNumber, int pageSize, Func<IRavenQueryable<T>, IQueryable<T>> querySelector = default);
2021-11-18 16:00:20 +01:00
/// <summary>
/// Get entities by query (by using the specified index)
/// </summary>
2021-11-23 15:43:21 +01:00
Task<Paged<T>> Load<TIndex>(int pageNumber, int pageSize, Func<IRavenQueryable<T>, IQueryable<T>> querySelector = default) where TIndex : AbstractCommonApiForIndexes, new();
2021-11-18 16:00:20 +01:00
/// <summary>
/// Get all entities from this collection.
/// Warning: Don't use this method for large collections. Stream the results instead.
/// </summary>
Task<List<T>> LoadAll();
/// <summary>
/// Stream the collection
/// </summary>
2021-11-23 15:43:21 +01:00
IAsyncEnumerable<T> Stream(Func<IRavenQueryable<T>, IQueryable<T>> expression);
2021-11-18 16:00:20 +01:00
/// <summary>
/// Get the change vector for a model (Proxy to IAsyncDocumentSession.GetChangeVectorFor<>)
/// </summary>
2021-12-12 15:41:51 +01:00
string GetChangeToken(T model);
2021-11-18 16:00:20 +01:00
/// <summary>
/// Validates an entity in this collection
/// </summary>
Task<ValidationResult> Validate(T model);
2021-11-19 12:03:36 +01:00
/// <summary>
2021-11-23 15:43:21 +01:00
/// Creates an entity with an optional validator
2021-11-19 12:03:36 +01:00
/// </summary>
2021-11-26 15:47:11 +01:00
Task<Result<T>> Create(T model);
2021-11-23 15:43:21 +01:00
/// <summary>
/// Updates an entity with an optional validator
/// </summary>
2021-11-26 15:47:11 +01:00
Task<Result<T>> Update(T model);
2021-11-19 12:03:36 +01:00
2021-12-29 15:29:33 +01:00
/// <summary>
/// Update sorting of entities on a specific level
/// </summary>
Task<Result<IOrderedEnumerable<T>>> Sort(string[] sortedIds);
2021-11-19 12:03:36 +01:00
/// <summary>
/// Deletes an entity
/// </summary>
2021-11-26 15:47:11 +01:00
Task<Result<T>> Delete(T model);
2021-11-18 16:00:20 +01:00
}