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
|
|
|
|
2021-12-30 11:11:34 +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
|
|
|
|
2021-12-01 13:23:44 +01:00
|
|
|
/// <inheritdoc />
|
2021-12-12 15:41:51 +01:00
|
|
|
public virtual string GetChangeToken(T model) => Operations.GetChangeToken(model);
|
2021-12-01 13:23:44 +01:00
|
|
|
|
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; }
|
|
|
|
|
|
2021-12-30 11:11:34 +01:00
|
|
|
/// <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
|
|
|
|
2021-12-01 13:23:44 +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-12-01 13:23:44 +01:00
|
|
|
|
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
|
|
|
}
|