rename to mixtape
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
using System;
|
||||
using System.Linq.Expressions;
|
||||
using ServiceStack.OrmLite;
|
||||
using Mixtape.Extensions;
|
||||
|
||||
namespace Mixtape.Sqlite;
|
||||
|
||||
public static class SqlExpressionExtensions
|
||||
{
|
||||
public static SqlExpression<T> Paging<T>(this SqlExpression<T> source, int pageNumber, int pageSize)
|
||||
{
|
||||
pageNumber = pageNumber.Limit(1, 10_000_000);
|
||||
pageSize = pageSize.Limit(1, 1_000);
|
||||
|
||||
if (pageNumber <= 0 || pageSize <= 0)
|
||||
{
|
||||
throw new NotSupportedException("Both pageNumber and pageSize must be greater than z_ero");
|
||||
}
|
||||
|
||||
return source.Skip((pageNumber - 1) * pageSize).Take(pageSize);
|
||||
}
|
||||
|
||||
public static SqlExpression<T> WhereIf<T>(this SqlExpression<T> source, Expression<Func<T, bool>> predicate, bool condition, Expression<Func<T, bool>> elsePredicate = null)
|
||||
{
|
||||
if (condition)
|
||||
{
|
||||
return source.Where(predicate);
|
||||
}
|
||||
|
||||
return elsePredicate != null ? source.Where(elsePredicate) : source;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
using System;
|
||||
using System.Data;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using ServiceStack.Data;
|
||||
using ServiceStack.OrmLite;
|
||||
using Mixtape.Configuration;
|
||||
using Mixtape.Models;
|
||||
using Mixtape.Modules;
|
||||
|
||||
namespace Mixtape.Sqlite;
|
||||
|
||||
public static class MixtapeBuilderExtensions
|
||||
{
|
||||
public static MixtapeBuilder AddSqlite(this MixtapeBuilder builder)
|
||||
{
|
||||
builder.AddModule<MixtapeSqliteModule>();
|
||||
return builder;
|
||||
}
|
||||
}
|
||||
|
||||
internal class MixtapeSqliteModule : MixtapeModule
|
||||
{
|
||||
public override void ConfigureServices(IServiceCollection services, IConfiguration configuration)
|
||||
{
|
||||
services.AddSingleton<IDbConnectionFactory>(CreateDbConnectionFactory);
|
||||
services.AddScoped<IDbConnection>(CreateDbConnection);
|
||||
services.AddScoped<IDbOperations, DbOperations>();
|
||||
services.AddScoped<StoreContext>();
|
||||
services.AddScoped<IEntityModifiedHandler, EmptyEntityModifiedHandler>();
|
||||
services.AddOptions<FlavorOptions>();
|
||||
services.AddOptions<SqliteOptions>().Bind(configuration.GetSection("Mixtape:Sqlite"));
|
||||
services.ConfigureOptions<ConfigureFlavorJsonOptions>();
|
||||
}
|
||||
|
||||
|
||||
protected IDbConnectionFactory CreateDbConnectionFactory(IServiceProvider services)
|
||||
{
|
||||
IMixtapeOptions options = services.GetService<IMixtapeOptions>();
|
||||
SqliteOptions sqliteOptions = options.For<SqliteOptions>();
|
||||
return new OrmLiteConnectionFactory(sqliteOptions.ConnectionString, SqliteDialect.Provider);
|
||||
}
|
||||
|
||||
|
||||
protected IDbConnection CreateDbConnection(IServiceProvider services)
|
||||
{
|
||||
IDbConnectionFactory factory = services.GetService<IDbConnectionFactory>();
|
||||
IMixtapeOptions options = services.GetService<IMixtapeOptions>();
|
||||
SqliteOptions sqliteOptions = options.For<SqliteOptions>();
|
||||
IDbConnection db = factory.CreateDbConnection();
|
||||
db.Open();
|
||||
sqliteOptions.OnConnectionCreate?.Invoke(db);
|
||||
return db;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using ServiceStack.OrmLite;
|
||||
using Mixtape.Models;
|
||||
|
||||
namespace Mixtape.Sqlite;
|
||||
|
||||
public partial class DbOperations : IDbOperations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public virtual Task<Result<T>> Delete<T>(T model) where T : MixtapeIdEntity, new()
|
||||
=> Delete<T>(model.Id);
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual async Task<Result<T>> Delete<T>(string id) where T : MixtapeIdEntity, new()
|
||||
{
|
||||
T model = await Load<T>(id);
|
||||
|
||||
if (model == null)
|
||||
{
|
||||
Logger.LogWarning("Could not delete entity (model is null) for type {type}", typeof(T));
|
||||
return Result<T>.Fail("@errors.ondelete.idnotfound");
|
||||
}
|
||||
|
||||
if (model is ISupportsSoftDelete softDeleteModel)
|
||||
{
|
||||
softDeleteModel.IsDeleted = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
await Db.DeleteByIdAsync<T>(model.Id);
|
||||
}
|
||||
|
||||
Logger.LogInformation("{id} ({type}) successfully deleted", typeof(T), model.Id);
|
||||
await EntityModifiedHandler.Deleted(model);
|
||||
|
||||
return Result<T>.Success();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Threading.Tasks;
|
||||
using ServiceStack.OrmLite;
|
||||
using Mixtape.Extensions;
|
||||
using Mixtape.Models;
|
||||
|
||||
namespace Mixtape.Sqlite;
|
||||
|
||||
public partial class DbOperations : IDbOperations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public virtual async Task<T> Load<T>(string id, string changeVector = null) where T : MixtapeIdEntity, new()
|
||||
{
|
||||
if (id.IsNullOrWhiteSpace())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (!changeVector.IsNullOrEmpty())
|
||||
{
|
||||
//return WhenActive(await GetRevision(changeVector)); // TODO
|
||||
}
|
||||
|
||||
return WhenActive(await Db.SingleByIdAsync<T>(id));
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual async Task<Dictionary<string, T>> Load<T>(IEnumerable<string> ids) where T : MixtapeIdEntity, new()
|
||||
{
|
||||
ids = ids.Distinct().ToArray();
|
||||
|
||||
List<T> models = await Db.SelectByIdsAsync<T>(ids);
|
||||
Dictionary<string, T> result = new();
|
||||
|
||||
foreach (string id in ids)
|
||||
{
|
||||
T model = models.FirstOrDefault(x => x.Id == id);
|
||||
result.Add(id, WhenActive(model));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual async Task<List<T>> LoadAsList<T>(IEnumerable<string> ids) where T : MixtapeIdEntity, new()
|
||||
{
|
||||
ids = ids.Distinct().ToArray();
|
||||
|
||||
List<T> models = await Db.SelectByIdsAsync<T>(ids);
|
||||
List<T> result = [];
|
||||
|
||||
foreach (string id in ids)
|
||||
{
|
||||
T model = models.FirstOrDefault(x => x.Id == id);
|
||||
if (WhenActive(model) != null)
|
||||
{
|
||||
result.Add(model);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual async Task<bool> Any<T>(Expression<Func<T, bool>> querySelector = null) where T : MixtapeIdEntity, new()
|
||||
{
|
||||
return await Db.ExistsAsync(querySelector ?? (x => true));
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual async Task<List<T>> Load<T>(Expression<Func<T, bool>> querySelector) where T : MixtapeIdEntity, new()
|
||||
{
|
||||
return await Db.SelectAsync(querySelector ?? (x => true));
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual async Task<T> Find<T>(Expression<Func<T, bool>> querySelector) where T : MixtapeIdEntity, new()
|
||||
{
|
||||
return await Db.SingleAsync(querySelector);
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual async Task<List<T>> LoadBySql<T>(Func<SqlExpression<T>, SqlExpression<T>> querySelector) where T : MixtapeIdEntity, new()
|
||||
{
|
||||
return await Db.SelectAsync(querySelector(Db.From<T>()));
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual async Task<List<T>> LoadAll<T>() where T : MixtapeIdEntity, new()
|
||||
{
|
||||
return await Db.SelectAsync<T>(x => true);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using FluentValidation.Results;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using ServiceStack.OrmLite;
|
||||
using Mixtape.Models;
|
||||
using Mixtape.Extensions;
|
||||
|
||||
namespace Mixtape.Sqlite;
|
||||
|
||||
public partial class DbOperations : IDbOperations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public virtual Task<Result<T>> Create<T>(T model, Func<T, Task<ValidationResult>> validate = null) where T : MixtapeIdEntity, new() => Save(model, validate);
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual Task<Result<T>> Update<T>(T model, Func<T, Task<ValidationResult>> validate = null) where T : MixtapeIdEntity, new() => Save(model, validate, true);
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual async Task<Result<T>> CreateOrUpdate<T>(T model, Func<T, Task<ValidationResult>> validate = null) where T : MixtapeIdEntity, new()
|
||||
{
|
||||
bool update = !model.Id.IsNullOrEmpty() && await Any<T>(x => x.Id == model.Id);
|
||||
return await Save(model, validate, update);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected virtual async Task<Result<T>> Save<T>(T model, Func<T, Task<ValidationResult>> validate = null, bool update = false) where T : MixtapeIdEntity, new()
|
||||
{
|
||||
if (model == null)
|
||||
{
|
||||
Logger.LogWarning("Could not create/update entity (model is null) for type {type}", typeof(T));
|
||||
return Result<T>.Fail("@errors.onsave.empty");
|
||||
}
|
||||
|
||||
// check if the Id for a model already exists
|
||||
if (!model.Id.IsNullOrEmpty())
|
||||
{
|
||||
T previousModel = await Db.SingleByIdAsync<T>(model.Id);
|
||||
|
||||
if (update && previousModel == null)
|
||||
{
|
||||
return Result<T>.Fail("@errors.onsave.noidmatch");
|
||||
}
|
||||
else if (!update && previousModel != null)
|
||||
{
|
||||
return Result<T>.Fail("@errors.oncreate.idmismatch");
|
||||
}
|
||||
}
|
||||
|
||||
// validate flavor
|
||||
if (model is ISupportsFlavors flavorModel && !flavorModel.Flavor.IsNullOrEmpty())
|
||||
{
|
||||
if (!Flavors.Exists<T>(flavorModel.Flavor))
|
||||
{
|
||||
Logger.LogWarning("Flavor {flavor} not found for type {type}", flavorModel.Flavor, typeof(T));
|
||||
return Result<T>.Fail("@errors.onsave.flavornotfound");
|
||||
}
|
||||
}
|
||||
|
||||
// prepare model
|
||||
PrepareForSave(model);
|
||||
|
||||
// run validator
|
||||
if (validate != null)
|
||||
{
|
||||
ValidationResult validation = await validate(model);
|
||||
|
||||
if (!validation.IsValid)
|
||||
{
|
||||
Logger.LogInformation("Validation failed for {id} ({errors})", model.Id, validation.Errors);
|
||||
return Result<T>.Fail(validation);
|
||||
}
|
||||
}
|
||||
|
||||
// create ID before-hand so interceptors can use it
|
||||
if (!update && !model.Id.HasValue())
|
||||
{
|
||||
model.Id = await GenerateId(model);
|
||||
}
|
||||
|
||||
// store our model
|
||||
await Db.SaveAsync(model);
|
||||
|
||||
string action = update ? "Updated" : "Created";
|
||||
if (model is MixtapeEntity mixtapeEntity)
|
||||
{
|
||||
Logger.LogInformation(action + " {id} with name {name}", model.Id, mixtapeEntity.Name);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.LogInformation(action + " {id}", model.Id);
|
||||
}
|
||||
|
||||
await EntityModifiedHandler.Saved(model, update);
|
||||
|
||||
return Result<T>.Success(model);
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual async Task Sort<T>(IEnumerable<string> ids) where T : MixtapeEntity, new()
|
||||
{
|
||||
List<T> items = await LoadAll<T>();
|
||||
|
||||
uint sort = 0;
|
||||
foreach (string id in ids)
|
||||
{
|
||||
T item = items.FirstOrDefault(x => x.Id == id);
|
||||
if (item != null)
|
||||
{
|
||||
sort += 10;
|
||||
item.Sort = sort;
|
||||
item.LastModifiedDate = DateTimeOffset.Now;
|
||||
}
|
||||
}
|
||||
await Db.UpdateAllAsync(items);
|
||||
foreach (T item in items)
|
||||
{
|
||||
await EntityModifiedHandler.Updated(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,216 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using FluentValidation.Results;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System.Linq.Expressions;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using ServiceStack.OrmLite;
|
||||
using Mixtape.Communication;
|
||||
using Mixtape.Context;
|
||||
using Mixtape.Models;
|
||||
using Mixtape.Utils;
|
||||
using Mixtape.Validation;
|
||||
|
||||
namespace Mixtape.Sqlite;
|
||||
|
||||
public partial class DbOperations : IDbOperations
|
||||
{
|
||||
protected IMixtapeContext Context { get; private set; }
|
||||
|
||||
protected FlavorOptions Flavors { get; }
|
||||
|
||||
protected IServiceProvider Services { get; }
|
||||
|
||||
protected IDbConnection Db { get; }
|
||||
|
||||
protected ILogger<IDbOperations> Logger { get; }
|
||||
|
||||
protected IEntityModifiedHandler EntityModifiedHandler { get; }
|
||||
|
||||
|
||||
public DbOperations(StoreContext context, IDbConnection db, ILogger<IDbOperations> logger, IHandlerHolder handler)
|
||||
{
|
||||
Context = context.Context;
|
||||
Services = context.Services;
|
||||
Flavors = context.Options.For<FlavorOptions>();
|
||||
Db = db;
|
||||
Logger = logger;
|
||||
EntityModifiedHandler = handler.Get<IEntityModifiedHandler>();
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool EnsureTableExists<T>() where T : MixtapeIdEntity
|
||||
{
|
||||
return Db.CreateTableIfNotExists<T>();
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public Task<string> GenerateId<T>(T model) where T : MixtapeIdEntity
|
||||
{
|
||||
return Task.FromResult(IdGenerator.Create(12));
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public T AutoSetIds<T>(T model)
|
||||
{
|
||||
return IdGenerator.Autofill(model);
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public T PrepareForSave<T>(T model) where T : MixtapeIdEntity
|
||||
{
|
||||
// set IDs
|
||||
AutoSetIds(model);
|
||||
|
||||
if (model is not MixtapeEntity mixtapeModel)
|
||||
{
|
||||
return model;
|
||||
}
|
||||
|
||||
// set default properties
|
||||
if (mixtapeModel.CreatedDate == default)
|
||||
{
|
||||
mixtapeModel.CreatedDate = DateTimeOffset.Now;
|
||||
}
|
||||
|
||||
// update name alias and last modified
|
||||
mixtapeModel.Alias = Safenames.Alias(mixtapeModel.Name);
|
||||
mixtapeModel.LastModifiedDate = DateTimeOffset.Now;
|
||||
mixtapeModel.Hash ??= IdGenerator.Create();
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<ValidationResult> Validate<T>(T model) where T : MixtapeIdEntity, new()
|
||||
{
|
||||
IMixtapeMergedValidator<T> validator = Services.GetService<IMixtapeMergedValidator<T>>();
|
||||
|
||||
if (validator == null)
|
||||
{
|
||||
return new();
|
||||
}
|
||||
|
||||
return await validator.ValidateAsync(model);
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual T WhenActive<T>(T model) where T : MixtapeIdEntity, new()
|
||||
{
|
||||
return model; // TODO should we really use this? I tried to get data in a custom backend but couldn't because of this
|
||||
//return model != null && (model is not MixtapeEntity || (model as MixtapeEntity).IsActive) && (model is not ISupportsSoftDelete || !(model as ISupportsSoftDelete).IsDeleted) ? model : default;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public interface IDbOperations
|
||||
{
|
||||
/// <summary>
|
||||
/// Create a table if not existing
|
||||
/// </summary>
|
||||
bool EnsureTableExists<T>() where T : MixtapeIdEntity;
|
||||
|
||||
/// <summary>
|
||||
/// Generate model Id by using configured document store conventions
|
||||
/// </summary>
|
||||
Task<string> GenerateId<T>(T model) where T : MixtapeIdEntity;
|
||||
|
||||
/// <summary>
|
||||
/// Do only return the model when it is set to active or inactive entities are included with IncludeInactive()
|
||||
/// </summary>
|
||||
T WhenActive<T>(T model) where T : MixtapeIdEntity, new();
|
||||
|
||||
/// <summary>
|
||||
/// Validates an entity
|
||||
/// </summary>
|
||||
Task<ValidationResult> Validate<T>(T model) where T : MixtapeIdEntity, new();
|
||||
|
||||
/// <summary>
|
||||
/// Generate values for all properties (incl. nested) which contain the [GenerateId] attribute
|
||||
/// </summary>
|
||||
T AutoSetIds<T>(T model);
|
||||
|
||||
/// <summary>
|
||||
/// Automatically fill base properties of a MixtapeEntity
|
||||
/// </summary>
|
||||
T PrepareForSave<T>(T model) where T : MixtapeIdEntity;
|
||||
|
||||
/// <summary>
|
||||
/// Get an entity by Id
|
||||
/// </summary>
|
||||
Task<T> Load<T>(string id, string changeVector = null) where T : MixtapeIdEntity, new();
|
||||
|
||||
/// <summary>
|
||||
/// Get entities by ids
|
||||
/// </summary>
|
||||
Task<Dictionary<string, T>> Load<T>(IEnumerable<string> ids) where T : MixtapeIdEntity, new();
|
||||
|
||||
/// <summary>
|
||||
/// Get entities by ids
|
||||
/// </summary>
|
||||
Task<List<T>> LoadAsList<T>(IEnumerable<string> ids) where T : MixtapeIdEntity, new();
|
||||
|
||||
/// <summary>
|
||||
/// Check if any items exist in this collection (with optional query)
|
||||
/// </summary>
|
||||
Task<bool> Any<T>(Expression<Func<T, bool>> querySelector = null) where T : MixtapeIdEntity, new();
|
||||
|
||||
/// <summary>
|
||||
/// Get entities by query
|
||||
/// </summary>
|
||||
Task<List<T>> Load<T>(Expression<Func<T, bool>> querySelector) where T : MixtapeIdEntity, new();
|
||||
|
||||
/// <summary>
|
||||
/// Find entity by query
|
||||
/// </summary>
|
||||
Task<T> Find<T>(Expression<Func<T, bool>> querySelector) where T : MixtapeIdEntity, new();
|
||||
|
||||
/// <summary>
|
||||
/// Get entities by sql query
|
||||
/// </summary>
|
||||
Task<List<T>> LoadBySql<T>(Func<SqlExpression<T>, SqlExpression<T>> querySelector) where T : MixtapeIdEntity, new();
|
||||
|
||||
/// <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<T>() where T : MixtapeIdEntity, new();
|
||||
|
||||
/// <summary>
|
||||
/// Creates an entity with an optional validator
|
||||
/// </summary>
|
||||
Task<Result<T>> Create<T>(T model, Func<T, Task<ValidationResult>> validate = null) where T : MixtapeIdEntity, new();
|
||||
|
||||
/// <summary>
|
||||
/// Updates an entity with an optional validator
|
||||
/// </summary>
|
||||
Task<Result<T>> Update<T>(T model, Func<T, Task<ValidationResult>> validate = null) where T : MixtapeIdEntity, new();
|
||||
|
||||
/// <summary>
|
||||
/// Checks if an entity exists (via ID) and creates or updates it afterwards accordingly
|
||||
/// </summary>
|
||||
Task<Result<T>> CreateOrUpdate<T>(T model, Func<T, Task<ValidationResult>> validate = null) where T : MixtapeIdEntity, new();
|
||||
|
||||
/// <summary>
|
||||
/// Updates sorting of all items in a collection based on the given enumerable
|
||||
/// </summary>
|
||||
Task Sort<T>(IEnumerable<string> ids) where T : MixtapeEntity, new();
|
||||
|
||||
/// <summary>
|
||||
/// Deletes an entity
|
||||
/// </summary>
|
||||
Task<Result<T>> Delete<T>(T model) where T : MixtapeIdEntity, new();
|
||||
|
||||
/// <summary>
|
||||
/// Deletes an entity
|
||||
/// </summary>
|
||||
Task<Result<T>> Delete<T>(string id) where T : MixtapeIdEntity, new();
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using System.Threading.Tasks;
|
||||
using Mixtape.Communication;
|
||||
using Mixtape.Models;
|
||||
|
||||
namespace Mixtape.Sqlite;
|
||||
|
||||
public interface IEntityModifiedHandler : IHandler
|
||||
{
|
||||
Task Saved<T>(T model, bool update) where T : MixtapeIdEntity, new() => update ? Updated(model) : Created(model);
|
||||
Task Created<T>(T model) where T : MixtapeIdEntity, new();
|
||||
Task Updated<T>(T model) where T : MixtapeIdEntity, new();
|
||||
Task Deleted<T>(T model) where T : MixtapeIdEntity, new();
|
||||
}
|
||||
|
||||
|
||||
public class EmptyEntityModifiedHandler : IEntityModifiedHandler
|
||||
{
|
||||
public Task Created<T>(T model) where T : MixtapeIdEntity, new() => Task.CompletedTask;
|
||||
public Task Updated<T>(T model) where T : MixtapeIdEntity, new() => Task.CompletedTask;
|
||||
public Task Deleted<T>(T model) where T : MixtapeIdEntity, new() => Task.CompletedTask;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
using System;
|
||||
using Mixtape.Communication;
|
||||
using Mixtape.Configuration;
|
||||
using Mixtape.Context;
|
||||
|
||||
namespace Mixtape.Sqlite;
|
||||
|
||||
public class StoreContext
|
||||
{
|
||||
public IMixtapeContext Context { get; private set; }
|
||||
|
||||
public IMixtapeOptions Options { get; private set; }
|
||||
|
||||
public IServiceProvider Services { get; private set; }
|
||||
|
||||
public IMessageAggregator Messages { get; private set; }
|
||||
|
||||
|
||||
public StoreContext(IMixtapeContext context, IServiceProvider serviceProvider, IMessageAggregator messages)
|
||||
{
|
||||
Options = context.Options;
|
||||
Context = context;
|
||||
Services = serviceProvider;
|
||||
Messages = messages;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
using System;
|
||||
using System.Data;
|
||||
|
||||
namespace Mixtape.Sqlite;
|
||||
|
||||
public class SqliteOptions
|
||||
{
|
||||
public string ConnectionString { get; set; }
|
||||
|
||||
public Action<IDbConnection> OnConnectionCreate { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<PackageId>Mixtape.Sqlite</PackageId>
|
||||
<Version>1.0.0</Version>
|
||||
<TargetFrameworks>net8.0;net9.0;net10.0</TargetFrameworks>
|
||||
<TypeScriptCompileBlocked>true</TypeScriptCompileBlocked>
|
||||
<RootNamespace>Mixtape.Sqlite</RootNamespace>
|
||||
<DebugType>embedded</DebugType>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="FluentValidation" Version="12.1.1" />
|
||||
<PackageReference Include="ServiceStack.OrmLite.Sqlite" Version="10.0.6" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Mixtape\Mixtape.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
Reference in New Issue
Block a user