Improved Category Ladders
This commit is contained in:
parent
ea6adeb58f
commit
3211b2dc85
@ -21,10 +21,7 @@ namespace DataLayer.Configurations
|
|||||||
entity.Ignore(nameof(Book.Narrators));
|
entity.Ignore(nameof(Book.Narrators));
|
||||||
entity.Ignore(nameof(Book.AudioFormat));
|
entity.Ignore(nameof(Book.AudioFormat));
|
||||||
entity.Ignore(nameof(Book.TitleWithSubtitle));
|
entity.Ignore(nameof(Book.TitleWithSubtitle));
|
||||||
//// these don't seem to matter
|
entity.Ignore(b => b.Categories);
|
||||||
//entity.Ignore(nameof(Book.AuthorNames));
|
|
||||||
//entity.Ignore(nameof(Book.NarratorNames));
|
|
||||||
//entity.Ignore(nameof(Book.HasPdfs));
|
|
||||||
|
|
||||||
// OwnsMany: "Can only ever appear on navigation properties of other entity types.
|
// OwnsMany: "Can only ever appear on navigation properties of other entity types.
|
||||||
// Are automatically loaded, and can only be tracked by a DbContext alongside their owner."
|
// Are automatically loaded, and can only be tracked by a DbContext alongside their owner."
|
||||||
@ -58,24 +55,6 @@ namespace DataLayer.Configurations
|
|||||||
// owns it 1:1, store in same table
|
// owns it 1:1, store in same table
|
||||||
b_udi.OwnsOne(udi => udi.Rating);
|
b_udi.OwnsOne(udi => udi.Rating);
|
||||||
});
|
});
|
||||||
|
|
||||||
entity
|
|
||||||
.Metadata
|
|
||||||
.FindNavigation(nameof(Book.ContributorsLink))
|
|
||||||
// PropertyAccessMode.Field : Contributions is a get-only property, not a field, so use its backing field
|
|
||||||
.SetPropertyAccessMode(PropertyAccessMode.Field);
|
|
||||||
|
|
||||||
entity
|
|
||||||
.Metadata
|
|
||||||
.FindNavigation(nameof(Book.SeriesLink))
|
|
||||||
// PropertyAccessMode.Field : Series is a get-only property, not a field, so use its backing field
|
|
||||||
.SetPropertyAccessMode(PropertyAccessMode.Field);
|
|
||||||
|
|
||||||
entity
|
|
||||||
.Metadata
|
|
||||||
.FindNavigation(nameof(Book.CategoriesLink))
|
|
||||||
// PropertyAccessMode.Field : Categories is a get-only property, not a field, so use its backing field
|
|
||||||
.SetPropertyAccessMode(PropertyAccessMode.Field);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Dinah.Core;
|
using Dinah.Core;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
@ -90,8 +91,8 @@ namespace DataLayer
|
|||||||
|
|
||||||
// non-ef-ctor init.s
|
// non-ef-ctor init.s
|
||||||
UserDefinedItem = new UserDefinedItem(this);
|
UserDefinedItem = new UserDefinedItem(this);
|
||||||
_contributorsLink = new HashSet<BookContributor>();
|
ContributorsLink = new HashSet<BookContributor>();
|
||||||
_categoriesLink = new HashSet<BookCategory>();
|
CategoriesLink = new HashSet<BookCategory>();
|
||||||
_seriesLink = new HashSet<SeriesBook>();
|
_seriesLink = new HashSet<SeriesBook>();
|
||||||
_supplements = new HashSet<Supplement>();
|
_supplements = new HashSet<Supplement>();
|
||||||
|
|
||||||
@ -113,19 +114,11 @@ namespace DataLayer
|
|||||||
}
|
}
|
||||||
|
|
||||||
#region contributors, authors, narrators
|
#region contributors, authors, narrators
|
||||||
// use uninitialised backing fields - this means we can detect if the collection was loaded
|
internal HashSet<BookContributor> ContributorsLink { get; private set; }
|
||||||
private HashSet<BookContributor> _contributorsLink;
|
|
||||||
// i'd like this to be internal but migration throws this exception when i try:
|
|
||||||
// Value cannot be null.
|
|
||||||
// Parameter name: property
|
|
||||||
public IEnumerable<BookContributor> ContributorsLink
|
|
||||||
=> _contributorsLink?
|
|
||||||
.OrderBy(bc => bc.Order)
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
public IEnumerable<Contributor> Authors => getContributions(Role.Author).Select(bc => bc.Contributor).ToList();
|
public IEnumerable<Contributor> Authors => ContributorsLink.ByRole(Role.Author).Select(bc => bc.Contributor).ToList();
|
||||||
public IEnumerable<Contributor> Narrators => getContributions(Role.Narrator).Select(bc => bc.Contributor).ToList();
|
public IEnumerable<Contributor> Narrators => ContributorsLink.ByRole(Role.Narrator).Select(bc => bc.Contributor).ToList();
|
||||||
public string Publisher => getContributions(Role.Publisher).SingleOrDefault()?.Contributor.Name;
|
public string Publisher => ContributorsLink.ByRole(Role.Publisher).SingleOrDefault()?.Contributor.Name;
|
||||||
|
|
||||||
public void ReplaceAuthors(IEnumerable<Contributor> authors, DbContext context = null)
|
public void ReplaceAuthors(IEnumerable<Contributor> authors, DbContext context = null)
|
||||||
=> replaceContributors(authors, Role.Author, context);
|
=> replaceContributors(authors, Role.Author, context);
|
||||||
@ -138,15 +131,19 @@ namespace DataLayer
|
|||||||
ArgumentValidator.EnsureEnumerableNotNullOrEmpty(newContributors, nameof(newContributors));
|
ArgumentValidator.EnsureEnumerableNotNullOrEmpty(newContributors, nameof(newContributors));
|
||||||
|
|
||||||
// the edge cases of doing local-loaded vs remote-only got weird. just load it
|
// the edge cases of doing local-loaded vs remote-only got weird. just load it
|
||||||
if (_contributorsLink is null)
|
if (ContributorsLink is null)
|
||||||
getEntry(context).Collection(s => s.ContributorsLink).Load();
|
getEntry(context).Collection(s => s.ContributorsLink).Load();
|
||||||
|
|
||||||
var roleContributions = getContributions(role);
|
var isIdentical
|
||||||
var isIdentical = roleContributions.Select(c => c.Contributor).SequenceEqual(newContributors);
|
= ContributorsLink
|
||||||
|
.ByRole(role)
|
||||||
|
.Select(c => c.Contributor)
|
||||||
|
.SequenceEqual(newContributors);
|
||||||
|
|
||||||
if (isIdentical)
|
if (isIdentical)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_contributorsLink.RemoveWhere(bc => bc.Role == role);
|
ContributorsLink.RemoveWhere(bc => bc.Role == role);
|
||||||
addNewContributors(newContributors, role);
|
addNewContributors(newContributors, role);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -155,14 +152,9 @@ namespace DataLayer
|
|||||||
byte order = 0;
|
byte order = 0;
|
||||||
var newContributionsEnum = newContributors.Select(c => new BookContributor(this, c, role, order++));
|
var newContributionsEnum = newContributors.Select(c => new BookContributor(this, c, role, order++));
|
||||||
var newContributions = new HashSet<BookContributor>(newContributionsEnum);
|
var newContributions = new HashSet<BookContributor>(newContributionsEnum);
|
||||||
_contributorsLink.UnionWith(newContributions);
|
ContributorsLink.UnionWith(newContributions);
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<BookContributor> getContributions(Role role)
|
|
||||||
=> ContributorsLink
|
|
||||||
.Where(a => a.Role == role)
|
|
||||||
.OrderBy(a => a.Order)
|
|
||||||
.ToList();
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
private Microsoft.EntityFrameworkCore.ChangeTracking.EntityEntry<Book> getEntry(DbContext context)
|
private Microsoft.EntityFrameworkCore.ChangeTracking.EntityEntry<Book> getEntry(DbContext context)
|
||||||
@ -176,25 +168,28 @@ namespace DataLayer
|
|||||||
|
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
#region categories
|
#region categories
|
||||||
private HashSet<BookCategory> _categoriesLink;
|
internal HashSet<BookCategory> CategoriesLink { get; private set; }
|
||||||
public IEnumerable<BookCategory> CategoriesLink => _categoriesLink?.ToList();
|
|
||||||
public void UpsertCategories(CategoryLadder ladder)
|
|
||||||
{
|
|
||||||
ArgumentValidator.EnsureNotNull(ladder, nameof(ladder));
|
|
||||||
|
|
||||||
var singleBookCategory = _categoriesLink.SingleOrDefault(bc => bc.CategoryLadder.Equals(ladder));
|
private ReadOnlyCollection<BookCategory> _categoriesReadOnly;
|
||||||
|
public ReadOnlyCollection<BookCategory> Categories
|
||||||
if (singleBookCategory is null)
|
|
||||||
_categoriesLink.Add(new BookCategory(this, ladder));
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
for (var i = 0; i < ladder._categories.Count; i++)
|
get
|
||||||
{
|
{
|
||||||
//Update the category name
|
if (_categoriesReadOnly?.SequenceEqual(CategoriesLink) is not true)
|
||||||
singleBookCategory.CategoryLadder._categories[i].Name = ladder._categories[i].Name;
|
_categoriesReadOnly = CategoriesLink.ToList().AsReadOnly();
|
||||||
|
return _categoriesReadOnly;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public void SetCategoryLadders(IEnumerable<CategoryLadder> ladders)
|
||||||
|
{
|
||||||
|
ArgumentValidator.EnsureNotNull(ladders, nameof(ladders));
|
||||||
|
|
||||||
|
//Replace all existing category ladders.
|
||||||
|
//Some books make have duplocate ladders
|
||||||
|
CategoriesLink.Clear();
|
||||||
|
CategoriesLink.UnionWith(ladders.Distinct().Select(l => new BookCategory(this, l)));
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,9 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.Linq;
|
||||||
using Dinah.Core;
|
using Dinah.Core;
|
||||||
|
|
||||||
|
#nullable enable
|
||||||
namespace DataLayer
|
namespace DataLayer
|
||||||
{
|
{
|
||||||
public class AudibleCategoryId
|
public class AudibleCategoryId
|
||||||
@ -16,12 +19,21 @@ namespace DataLayer
|
|||||||
public class Category
|
public class Category
|
||||||
{
|
{
|
||||||
internal int CategoryId { get; private set; }
|
internal int CategoryId { get; private set; }
|
||||||
public string AudibleCategoryId { get; private set; }
|
public string? AudibleCategoryId { get; private set; }
|
||||||
|
|
||||||
public string Name { get; internal set; }
|
public string? Name { get; internal set; }
|
||||||
|
|
||||||
internal List<CategoryLadder> _categoryLadders = new();
|
internal List<CategoryLadder> _categoryLadders = new();
|
||||||
public IReadOnlyCollection<CategoryLadder> CategoryLadders => _categoryLadders.AsReadOnly();
|
private ReadOnlyCollection<CategoryLadder>? _categoryLaddersReadOnly;
|
||||||
|
public ReadOnlyCollection<CategoryLadder> CategoryLadders
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_categoryLaddersReadOnly?.SequenceEqual(_categoryLadders) is not true)
|
||||||
|
_categoryLaddersReadOnly = _categoryLadders.AsReadOnly();
|
||||||
|
return _categoryLaddersReadOnly;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private Category() { }
|
private Category() { }
|
||||||
/// <summary>special id class b/c it's too easy to get string order mixed up</summary>
|
/// <summary>special id class b/c it's too easy to get string order mixed up</summary>
|
||||||
|
|||||||
@ -4,6 +4,7 @@ using System.Collections.Generic;
|
|||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
|
#nullable enable
|
||||||
namespace DataLayer
|
namespace DataLayer
|
||||||
{
|
{
|
||||||
public class CategoryLadder : IEquatable<CategoryLadder>
|
public class CategoryLadder : IEquatable<CategoryLadder>
|
||||||
@ -11,10 +12,19 @@ namespace DataLayer
|
|||||||
internal int CategoryLadderId { get; private set; }
|
internal int CategoryLadderId { get; private set; }
|
||||||
|
|
||||||
internal List<Category> _categories;
|
internal List<Category> _categories;
|
||||||
public ReadOnlyCollection<Category> Categories => _categories.AsReadOnly();
|
private ReadOnlyCollection<Category>? _categoriesReadOnly;
|
||||||
|
public ReadOnlyCollection<Category> Categories
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_categoriesReadOnly?.SequenceEqual(_categories) is not true)
|
||||||
|
_categoriesReadOnly = _categories.AsReadOnly();
|
||||||
|
return _categoriesReadOnly;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private HashSet<BookCategory> _booksLink;
|
private HashSet<BookCategory>? _booksLink;
|
||||||
public IEnumerable<BookCategory> BooksLink => _booksLink?.ToList();
|
public IEnumerable<BookCategory>? BooksLink => _booksLink?.ToList();
|
||||||
private CategoryLadder() { _categories = new(); }
|
private CategoryLadder() { _categories = new(); }
|
||||||
public CategoryLadder(List<Category> categories)
|
public CategoryLadder(List<Category> categories)
|
||||||
{
|
{
|
||||||
@ -32,16 +42,16 @@ namespace DataLayer
|
|||||||
return hashCode.ToHashCode();
|
return hashCode.ToHashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Equals(CategoryLadder other)
|
public bool Equals(CategoryLadder? other)
|
||||||
{
|
=> other?._categories is not null
|
||||||
if (other?._categories is null)
|
&& Equals(other._categories.Select(c => c.AudibleCategoryId));
|
||||||
return false;
|
|
||||||
|
|
||||||
return Equals(other._categories.Select(c => c.AudibleCategoryId));
|
public bool Equals(IEnumerable<string?>? categoryIds)
|
||||||
}
|
=> categoryIds is not null
|
||||||
public bool Equals(IEnumerable<string> categoryIds)
|
&& _categories.Select(c => c.AudibleCategoryId).SequenceEqual(categoryIds);
|
||||||
=> _categories.Select(c => c.AudibleCategoryId).SequenceEqual(categoryIds);
|
|
||||||
public override bool Equals(object obj) => obj is CategoryLadder other && Equals(other);
|
public override bool Equals(object? obj)
|
||||||
|
=> obj is CategoryLadder other && Equals(other);
|
||||||
|
|
||||||
public override string ToString() => string.Join(" > ", _categories.Select(c => c.Name));
|
public override string ToString() => string.Join(" > ", _categories.Select(c => c.Name));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,6 +8,11 @@ namespace DataLayer
|
|||||||
{
|
{
|
||||||
public static class EntityExtensions
|
public static class EntityExtensions
|
||||||
{
|
{
|
||||||
|
public static IEnumerable<BookContributor> ByRole(this IEnumerable<BookContributor> contributors, Role role)
|
||||||
|
=> contributors
|
||||||
|
.Where(a => a.Role == role)
|
||||||
|
.OrderBy(a => a.Order);
|
||||||
|
|
||||||
public static string TitleSortable(this Book book) => Formatters.GetSortName(book.Title + book.Subtitle);
|
public static string TitleSortable(this Book book) => Formatters.GetSortName(book.Title + book.Subtitle);
|
||||||
|
|
||||||
public static string AuthorNames(this Book book) => string.Join(", ", book.Authors.Select(a => a.Name));
|
public static string AuthorNames(this Book book) => string.Join(", ", book.Authors.Select(a => a.Name));
|
||||||
|
|||||||
@ -11,8 +11,8 @@ using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
|||||||
namespace DataLayer.Migrations
|
namespace DataLayer.Migrations
|
||||||
{
|
{
|
||||||
[DbContext(typeof(LibationContext))]
|
[DbContext(typeof(LibationContext))]
|
||||||
[Migration("20230717220642_AddCategoriesList")]
|
[Migration("20230718214617_AddCategoryLadder")]
|
||||||
partial class AddCategoriesList
|
partial class AddCategoryLadder
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
@ -144,14 +144,6 @@ namespace DataLayer.Migrations
|
|||||||
b.HasIndex("AudibleCategoryId");
|
b.HasIndex("AudibleCategoryId");
|
||||||
|
|
||||||
b.ToTable("Categories");
|
b.ToTable("Categories");
|
||||||
|
|
||||||
b.HasData(
|
|
||||||
new
|
|
||||||
{
|
|
||||||
CategoryId = -1,
|
|
||||||
AudibleCategoryId = "",
|
|
||||||
Name = ""
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("DataLayer.CategoryLadder", b =>
|
modelBuilder.Entity("DataLayer.CategoryLadder", b =>
|
||||||
@ -163,12 +155,6 @@ namespace DataLayer.Migrations
|
|||||||
b.HasKey("CategoryLadderId");
|
b.HasKey("CategoryLadderId");
|
||||||
|
|
||||||
b.ToTable("CategoryLadders");
|
b.ToTable("CategoryLadders");
|
||||||
|
|
||||||
b.HasData(
|
|
||||||
new
|
|
||||||
{
|
|
||||||
CategoryLadderId = -1
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("DataLayer.Contributor", b =>
|
modelBuilder.Entity("DataLayer.Contributor", b =>
|
||||||
@ -5,7 +5,7 @@
|
|||||||
namespace DataLayer.Migrations
|
namespace DataLayer.Migrations
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public partial class AddCategoriesList : Migration
|
public partial class AddCategoryLadder : Migration
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override void Up(MigrationBuilder migrationBuilder)
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
@ -26,6 +26,11 @@ namespace DataLayer.Migrations
|
|||||||
name: "IX_Books_CategoryId",
|
name: "IX_Books_CategoryId",
|
||||||
table: "Books");
|
table: "Books");
|
||||||
|
|
||||||
|
migrationBuilder.DeleteData(
|
||||||
|
table: "Categories",
|
||||||
|
keyColumn: "CategoryId",
|
||||||
|
keyValue: -1);
|
||||||
|
|
||||||
migrationBuilder.DropColumn(
|
migrationBuilder.DropColumn(
|
||||||
name: "ParentCategoryCategoryId",
|
name: "ParentCategoryCategoryId",
|
||||||
table: "Categories");
|
table: "Categories");
|
||||||
@ -94,11 +99,6 @@ namespace DataLayer.Migrations
|
|||||||
onDelete: ReferentialAction.Cascade);
|
onDelete: ReferentialAction.Cascade);
|
||||||
});
|
});
|
||||||
|
|
||||||
migrationBuilder.InsertData(
|
|
||||||
table: "CategoryLadders",
|
|
||||||
column: "CategoryLadderId",
|
|
||||||
value: -1);
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
migrationBuilder.CreateIndex(
|
||||||
name: "IX_BookCategory_BookId",
|
name: "IX_BookCategory_BookId",
|
||||||
table: "BookCategory",
|
table: "BookCategory",
|
||||||
@ -140,12 +140,10 @@ namespace DataLayer.Migrations
|
|||||||
nullable: false,
|
nullable: false,
|
||||||
defaultValue: 0);
|
defaultValue: 0);
|
||||||
|
|
||||||
migrationBuilder.UpdateData(
|
migrationBuilder.InsertData(
|
||||||
table: "Categories",
|
table: "Categories",
|
||||||
keyColumn: "CategoryId",
|
columns: new[] { "CategoryId", "AudibleCategoryId", "Name", "ParentCategoryCategoryId" },
|
||||||
keyValue: -1,
|
values: new object[] { -1, "", "", null });
|
||||||
column: "ParentCategoryCategoryId",
|
|
||||||
value: null);
|
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
migrationBuilder.CreateIndex(
|
||||||
name: "IX_Categories_ParentCategoryCategoryId",
|
name: "IX_Categories_ParentCategoryCategoryId",
|
||||||
@ -141,14 +141,6 @@ namespace DataLayer.Migrations
|
|||||||
b.HasIndex("AudibleCategoryId");
|
b.HasIndex("AudibleCategoryId");
|
||||||
|
|
||||||
b.ToTable("Categories");
|
b.ToTable("Categories");
|
||||||
|
|
||||||
b.HasData(
|
|
||||||
new
|
|
||||||
{
|
|
||||||
CategoryId = -1,
|
|
||||||
AudibleCategoryId = "",
|
|
||||||
Name = ""
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("DataLayer.CategoryLadder", b =>
|
modelBuilder.Entity("DataLayer.CategoryLadder", b =>
|
||||||
@ -160,12 +152,6 @@ namespace DataLayer.Migrations
|
|||||||
b.HasKey("CategoryLadderId");
|
b.HasKey("CategoryLadderId");
|
||||||
|
|
||||||
b.ToTable("CategoryLadders");
|
b.ToTable("CategoryLadders");
|
||||||
|
|
||||||
b.HasData(
|
|
||||||
new
|
|
||||||
{
|
|
||||||
CategoryLadderId = -1
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("DataLayer.Contributor", b =>
|
modelBuilder.Entity("DataLayer.Contributor", b =>
|
||||||
|
|||||||
11
Source/DataLayer/QueryObjects/CategoryQueries.cs
Normal file
11
Source/DataLayer/QueryObjects/CategoryQueries.cs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace DataLayer
|
||||||
|
{
|
||||||
|
public static class CategoryQueries
|
||||||
|
{
|
||||||
|
public static IQueryable<CategoryLadder> GetCategoryLadders(this LibationContext context)
|
||||||
|
=> context.CategoryLadders.Include(c => c._categories);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -188,13 +188,15 @@ namespace DtoImporterService
|
|||||||
|
|
||||||
if (item.CategoryLadders is not null)
|
if (item.CategoryLadders is not null)
|
||||||
{
|
{
|
||||||
|
var ladders = new List<DataLayer.CategoryLadder>();
|
||||||
foreach (var ladder in item.CategoryLadders.Select(cl => cl.Ladder).Where(l => l?.Length > 0))
|
foreach (var ladder in item.CategoryLadders.Select(cl => cl.Ladder).Where(l => l?.Length > 0))
|
||||||
{
|
{
|
||||||
var categoryIds = ladder.Select(l => l.CategoryId).ToList();
|
var categoryIds = ladder.Select(l => l.CategoryId).ToList();
|
||||||
var cata = categoryImporter.LadderCache.Single(c => c.Equals(categoryIds));
|
ladders.Add(categoryImporter.LadderCache.Single(c => c.Equals(categoryIds)));
|
||||||
|
|
||||||
book.UpsertCategories(cata);
|
|
||||||
}
|
}
|
||||||
|
//Set all ladders at once so ladders that have been
|
||||||
|
//removed by audible can be removed from the DB
|
||||||
|
book.SetCategoryLadders(ladders);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -12,23 +12,15 @@ namespace DtoImporterService
|
|||||||
{
|
{
|
||||||
protected override IValidator Validator => new CategoryValidator();
|
protected override IValidator Validator => new CategoryValidator();
|
||||||
|
|
||||||
private Dictionary<string, Category> Cache { get; set; } = new();
|
private Dictionary<string, Category> CategoryCache { get; set; } = new();
|
||||||
public HashSet<DataLayer.CategoryLadder> LadderCache { get; private set; } = new();
|
public HashSet<DataLayer.CategoryLadder> LadderCache { get; private set; } = new();
|
||||||
|
|
||||||
public CategoryImporter(LibationContext context) : base(context) { }
|
public CategoryImporter(LibationContext context) : base(context) { }
|
||||||
|
|
||||||
protected override int DoImport(IEnumerable<ImportItem> importItems)
|
protected override int DoImport(IEnumerable<ImportItem> importItems)
|
||||||
{
|
{
|
||||||
// get distinct
|
|
||||||
var categoryIds = importItems
|
|
||||||
.Select(i => i.DtoItem)
|
|
||||||
.GetCategoriesDistinct()
|
|
||||||
.Select(c => c.CategoryId)
|
|
||||||
.Distinct()
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
// load db existing => .Local
|
// load db existing => .Local
|
||||||
loadLocal_categories(categoryIds);
|
loadLocal_categories();
|
||||||
|
|
||||||
// upsert
|
// upsert
|
||||||
var categoryLadders = importItems
|
var categoryLadders = importItems
|
||||||
@ -41,14 +33,11 @@ namespace DtoImporterService
|
|||||||
return qtyNew;
|
return qtyNew;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadLocal_categories(List<string> categoryIds)
|
private void loadLocal_categories()
|
||||||
{
|
{
|
||||||
// load existing => local
|
// load existing => local
|
||||||
Cache = DbContext.Categories
|
LadderCache = DbContext.GetCategoryLadders().ToHashSet();
|
||||||
.Where(c => categoryIds.Contains(c.AudibleCategoryId))
|
CategoryCache = LadderCache.SelectMany(cl => cl.Categories).ToDictionarySafe(c => c.AudibleCategoryId);
|
||||||
.ToDictionarySafe(c => c.AudibleCategoryId);
|
|
||||||
|
|
||||||
LadderCache = DbContext.CategoryLadders.ToHashSet();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// only use after loading contributors => local
|
// only use after loading contributors => local
|
||||||
@ -65,10 +54,9 @@ namespace DtoImporterService
|
|||||||
var id = ladder[i].CategoryId;
|
var id = ladder[i].CategoryId;
|
||||||
var name = ladder[i].CategoryName;
|
var name = ladder[i].CategoryName;
|
||||||
|
|
||||||
if (!Cache.TryGetValue(id, out var category))
|
if (!CategoryCache.TryGetValue(id, out var category))
|
||||||
{
|
{
|
||||||
category = addCategory(id, name);
|
category = addCategory(id, name);
|
||||||
qtyNew++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
categories.Add(category);
|
categories.Add(category);
|
||||||
@ -111,7 +99,7 @@ namespace DtoImporterService
|
|||||||
var entityEntry = DbContext.Categories.Add(category);
|
var entityEntry = DbContext.Categories.Add(category);
|
||||||
var entity = entityEntry.Entity;
|
var entity = entityEntry.Entity;
|
||||||
|
|
||||||
Cache.Add(entity.AudibleCategoryId, entity);
|
CategoryCache.Add(entity.AudibleCategoryId, entity);
|
||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user