Solving bugs with the database mapping & adding a find function

This commit is contained in:
Zoe Roux 2020-08-18 22:41:24 +02:00
parent b7a5b0579a
commit 828f4d3f47
15 changed files with 62 additions and 64 deletions

View File

@ -78,7 +78,7 @@ namespace Kyoo.Controllers
{
Task<T> Get(int id);
Task<T> Get(string slug);
async Task<T> Get(Expression<Func<T, bool>> where) => (await GetAll(where, limit: 1)).FirstOrDefault();
Task<T> Get(Expression<Func<T, bool>> where);
Task<ICollection<T>> Search(string query);
Task<ICollection<T>> GetAll(Expression<Func<T, bool>> where = null,

View File

@ -27,7 +27,7 @@ namespace Kyoo.Models
public static Studio Default()
{
return new Studio("unknow", "Unknow Studio");
return new Studio("unknown", "Unknown Studio");
}
}
}

View File

@ -5,6 +5,7 @@ using System.Globalization;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.ExceptionServices;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
@ -259,13 +260,21 @@ namespace Kyoo
return string.Empty;
return "?" + string.Join('&', query.Select(x => $"{x.Key}={x.Value}"));
}
[System.Diagnostics.CodeAnalysis.DoesNotReturn]
public static void ReThrow([NotNull] this Exception ex)
{
if (ex == null)
throw new ArgumentNullException(nameof(ex));
ExceptionDispatchInfo.Capture(ex).Throw();
}
public static Task<T> Then<T>(this Task<T> task, Action<T> map)
{
return task.ContinueWith(x =>
{
if (x.IsFaulted)
throw x.Exception!.InnerException!;
x.Exception!.InnerException!.ReThrow();
if (x.IsCanceled)
throw new TaskCanceledException();
map(x.Result);
@ -278,7 +287,7 @@ namespace Kyoo
return task.ContinueWith(x =>
{
if (x.IsFaulted)
throw x.Exception!.InnerException!;
x.Exception!.InnerException!.ReThrow();
if (x.IsCanceled)
throw new TaskCanceledException();
return map(x.Result);
@ -290,7 +299,7 @@ namespace Kyoo
return task.ContinueWith(x =>
{
if (x.IsFaulted)
throw x.Exception!.InnerException!;
x.Exception!.InnerException!.ReThrow();
if (x.IsCanceled)
throw new TaskCanceledException();
return (T)((dynamic)x).Result;

View File

@ -45,6 +45,11 @@ namespace Kyoo.Controllers
{
return Database.Set<T>().FirstOrDefaultAsync(x => x.Slug == slug);
}
public virtual Task<T> Get(Expression<Func<T, bool>> predicate)
{
return Database.Set<T>().FirstOrDefaultAsync(predicate);
}
public virtual Task<ICollection<T>> GetAll(Expression<Func<T, bool>> where = null,
Sort<T> sort = default,
@ -95,8 +100,14 @@ namespace Kyoo.Controllers
return await query.ToListAsync();
}
public abstract Task<T> Create([NotNull] T obj);
public virtual async Task<T> Create([NotNull] T obj)
{
if (obj == null)
throw new ArgumentNullException(nameof(obj));
await Validate(obj);
return obj;
}
public virtual async Task<T> CreateIfNotExists(T obj)
{
@ -139,6 +150,9 @@ namespace Kyoo.Controllers
protected virtual Task Validate(T ressource)
{
if (ressource.Slug == null)
throw new ArgumentException("Ressource can't have null as a slug.");
foreach (PropertyInfo property in typeof(T).GetProperties()
.Where(x => typeof(IEnumerable).IsAssignableFrom(x.PropertyType)
&& !typeof(string).IsAssignableFrom(x.PropertyType)))
@ -201,6 +215,11 @@ namespace Kyoo.Controllers
return base.Get(slug).Cast<T>();
}
public Task<T> Get(Expression<Func<T, bool>> predicate)
{
return Get(predicate.Convert<Func<TInternal, bool>>()).Cast<T>();
}
public abstract Task<ICollection<T>> Search(string query);
public virtual Task<ICollection<T>> GetAll(Expression<Func<T, bool>> where = null,
@ -224,8 +243,6 @@ namespace Kyoo.Controllers
return items.ToList<T>();
}
public abstract override Task<TInternal> Create(TInternal obj);
Task<T> IRepository<T>.Create(T item)
{

View File

@ -52,9 +52,7 @@ namespace Kyoo.Controllers
public override async Task<CollectionDE> Create(CollectionDE obj)
{
if (obj == null)
throw new ArgumentNullException(nameof(obj));
await base.Create(obj);
_database.Entry(obj).State = EntityState.Added;
await _database.SaveChangesAsync($"Trying to insert a duplicated collection (slug {obj.Slug} already exists).");
return obj;
@ -82,7 +80,7 @@ namespace Kyoo.Controllers
{
ICollection<Collection> collections = await ApplyFilters(_database.CollectionLinks
.Where(x => x.ShowID == showID)
.Select(x => x.Collection as CollectionDE),
.Select(x => (CollectionDE)x.Collection),
where,
sort,
limit);
@ -98,7 +96,7 @@ namespace Kyoo.Controllers
{
ICollection<Collection> collections = await ApplyFilters(_database.CollectionLinks
.Where(x => x.Show.Slug == showSlug)
.Select(x => x.Collection as CollectionDE),
.Select(x => (CollectionDE)x.Collection),
where,
sort,
limit);
@ -114,7 +112,7 @@ namespace Kyoo.Controllers
{
ICollection<Collection> collections = await ApplyFilters(_database.LibraryLinks
.Where(x => x.LibraryID == id && x.CollectionID != null)
.Select(x => x.Collection as CollectionDE),
.Select(x => (CollectionDE)x.Collection),
where,
sort,
limit);
@ -130,7 +128,7 @@ namespace Kyoo.Controllers
{
ICollection<Collection> collections = await ApplyFilters(_database.LibraryLinks
.Where(x => x.Library.Slug == slug && x.CollectionID != null)
.Select(x => x.Collection as CollectionDE),
.Select(x => (CollectionDE)x.Collection),
where,
sort,
limit);

View File

@ -97,10 +97,7 @@ namespace Kyoo.Controllers
public override async Task<Episode> Create(Episode obj)
{
if (obj == null)
throw new ArgumentNullException(nameof(obj));
await Validate(obj);
await base.Create(obj);
_database.Entry(obj).State = EntityState.Added;
if (obj.ExternalIDs != null)
foreach (MetadataID entry in obj.ExternalIDs)

View File

@ -47,9 +47,7 @@ namespace Kyoo.Controllers
public override async Task<GenreDE> Create(GenreDE obj)
{
if (obj == null)
throw new ArgumentNullException(nameof(obj));
await base.Create(obj);
_database.Entry(obj).State = EntityState.Added;
await _database.SaveChangesAsync($"Trying to insert a duplicated genre (slug {obj.Slug} already exists).");
return obj;
@ -73,7 +71,7 @@ namespace Kyoo.Controllers
Pagination limit = default)
{
ICollection<Genre> genres = await ApplyFilters(_database.GenreLinks.Where(x => x.ShowID == showID)
.Select(x => x.Genre as GenreDE),
.Select(x => (GenreDE)x.Genre),
where,
sort,
limit);
@ -89,7 +87,7 @@ namespace Kyoo.Controllers
{
ICollection<Genre> genres = await ApplyFilters(_database.GenreLinks
.Where(x => x.Show.Slug == showSlug)
.Select(x => x.Genre as GenreDE),
.Select(x => (GenreDE)x.Genre),
where,
sort,
limit);

View File

@ -52,10 +52,7 @@ namespace Kyoo.Controllers
public override async Task<LibraryDE> Create(LibraryDE obj)
{
if (obj == null)
throw new ArgumentNullException(nameof(obj));
await Validate(obj);
await base.Create(obj);
_database.Entry(obj).State = EntityState.Added;
if (obj.ProviderLinks != null)
foreach (ProviderLink entry in obj.ProviderLinks)
@ -103,7 +100,7 @@ namespace Kyoo.Controllers
{
ICollection<Library> libraries = await ApplyFilters(_database.LibraryLinks
.Where(x => x.ShowID == showID)
.Select(x => x.Library as LibraryDE),
.Select(x => (LibraryDE)x.Library),
where,
sort,
limit);
@ -119,7 +116,7 @@ namespace Kyoo.Controllers
{
ICollection<Library> libraries = await ApplyFilters(_database.LibraryLinks
.Where(x => x.Show.Slug == showSlug)
.Select(x => x.Library as LibraryDE),
.Select(x => (LibraryDE)x.Library),
where,
sort,
limit);
@ -135,7 +132,7 @@ namespace Kyoo.Controllers
{
ICollection<Library> libraries = await ApplyFilters(_database.LibraryLinks
.Where(x => x.CollectionID == id)
.Select(x => x.Library as LibraryDE),
.Select(x => (LibraryDE)x.Library),
where,
sort,
limit);
@ -151,7 +148,7 @@ namespace Kyoo.Controllers
{
ICollection<Library> libraries = await ApplyFilters(_database.LibraryLinks
.Where(x => x.Collection.Slug == slug)
.Select(x => x.Library as LibraryDE),
.Select(x => (LibraryDE)x.Library),
where,
sort,
limit);

View File

@ -52,10 +52,7 @@ namespace Kyoo.Controllers
public override async Task<People> Create(People obj)
{
if (obj == null)
throw new ArgumentNullException(nameof(obj));
await Validate(obj);
await base.Create(obj);
_database.Entry(obj).State = EntityState.Added;
if (obj.ExternalIDs != null)
foreach (MetadataID entry in obj.ExternalIDs)

View File

@ -29,11 +29,7 @@ namespace Kyoo.Controllers
public override async Task<ProviderID> Create(ProviderID obj)
{
if (obj == null)
throw new ArgumentNullException(nameof(obj));
if (obj.Slug == null)
throw new ArgumentException($"Provider's slug can't be null (name: {obj.Name}).");
await base.Create(obj);
_database.Entry(obj).State = EntityState.Added;
await _database.SaveChangesAsync($"Trying to insert a duplicated provider (slug {obj.Slug} already exists).");

View File

@ -80,10 +80,7 @@ namespace Kyoo.Controllers
public override async Task<Season> Create(Season obj)
{
if (obj == null)
throw new ArgumentNullException(nameof(obj));
await Validate(obj);
await base.Create(obj);
_database.Entry(obj).State = EntityState.Added;
if (obj.ExternalIDs != null)
foreach (MetadataID entry in obj.ExternalIDs)

View File

@ -88,10 +88,7 @@ namespace Kyoo.Controllers
public override async Task<ShowDE> Create(ShowDE obj)
{
if (obj == null)
throw new ArgumentNullException(nameof(obj));
await Validate(obj);
await base.Create(obj);
_database.Entry(obj).State = EntityState.Added;
if (obj.GenreLinks != null)
foreach (GenreLink entry in obj.GenreLinks)
@ -190,7 +187,7 @@ namespace Kyoo.Controllers
{
ICollection<Show> shows = await ApplyFilters(_database.LibraryLinks
.Where(x => x.LibraryID == id && x.ShowID != null)
.Select(x => x.Show as ShowDE),
.Select(x => (ShowDE)x.Show),
where,
sort,
limit);
@ -206,7 +203,7 @@ namespace Kyoo.Controllers
{
ICollection<Show> shows = await ApplyFilters(_database.LibraryLinks
.Where(x => x.Library.Slug == slug && x.ShowID != null)
.Select(x => x.Show as ShowDE),
.Select(x => (ShowDE)x.Show),
where,
sort,
limit);
@ -222,7 +219,7 @@ namespace Kyoo.Controllers
{
ICollection<Show> shows = await ApplyFilters(_database.CollectionLinks
.Where(x => x.CollectionID== id)
.Select(x => x.Show as ShowDE),
.Select(x => (ShowDE)x.Show),
where,
sort,
limit);
@ -238,7 +235,7 @@ namespace Kyoo.Controllers
{
ICollection<Show> shows = await ApplyFilters(_database.CollectionLinks
.Where(x => x.Collection.Slug == slug)
.Select(x => x.Show as ShowDE),
.Select(x => (ShowDE)x.Show),
where,
sort,
limit);

View File

@ -30,9 +30,7 @@ namespace Kyoo.Controllers
public override async Task<Studio> Create(Studio obj)
{
if (obj == null)
throw new ArgumentNullException(nameof(obj));
await base.Create(obj);
_database.Entry(obj).State = EntityState.Added;
await _database.SaveChangesAsync($"Trying to insert a duplicated studio (slug {obj.Slug} already exists).");
return obj;

View File

@ -68,14 +68,11 @@ namespace Kyoo.Controllers
public override async Task<Track> Create(Track obj)
{
if (obj == null)
throw new ArgumentNullException(nameof(obj));
if (obj.EpisodeID <= 0)
throw new InvalidOperationException($"Can't store a track not related to any episode (episodeID: {obj.EpisodeID}).");
await base.Create(obj);
_database.Entry(obj).State = EntityState.Added;
await _database.SaveChangesAsync($"Trying to insert a duplicated track (slug {obj.Slug} already exists).");
return obj;
}

View File

@ -46,9 +46,9 @@ namespace Kyoo
services.AddDbContext<DatabaseContext>(options =>
{
options.UseLazyLoadingProxies()
.UseNpgsql(_configuration.GetConnectionString("Database"))
.EnableSensitiveDataLogging()
.UseLoggerFactory(LoggerFactory.Create(builder => builder.AddConsole()));
.UseNpgsql(_configuration.GetConnectionString("Database"));
// .EnableSensitiveDataLogging()
// .UseLoggerFactory(LoggerFactory.Create(builder => builder.AddConsole()));
}, ServiceLifetime.Transient);
services.AddDbContext<IdentityDatabase>(options =>