NoTracking() to simplify confusing EF Core state. Tracking is now only used during mass import, not in UI
This commit is contained in:
parent
3c1db55a95
commit
85c18c8334
@ -104,8 +104,11 @@ namespace ApplicationServices
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
book.UserDefinedItem.Tags = newTags;
|
var udi = book.UserDefinedItem;
|
||||||
|
|
||||||
|
// Attach() NoTracking entities before SaveChanges()
|
||||||
|
udi.Tags = newTags;
|
||||||
|
context.Attach(udi).State = Microsoft.EntityFrameworkCore.EntityState.Modified;
|
||||||
var qtyChanges = context.SaveChanges();
|
var qtyChanges = context.SaveChanges();
|
||||||
|
|
||||||
if (qtyChanges > 0)
|
if (qtyChanges > 0)
|
||||||
|
|||||||
@ -11,7 +11,7 @@ namespace DataLayer
|
|||||||
public static Book GetBook_Flat_NoTracking(this LibationContext context, string productId)
|
public static Book GetBook_Flat_NoTracking(this LibationContext context, string productId)
|
||||||
=> context
|
=> context
|
||||||
.Books
|
.Books
|
||||||
.AsNoTracking()
|
.AsNoTrackingWithIdentityResolution()
|
||||||
.GetBook(productId);
|
.GetBook(productId);
|
||||||
|
|
||||||
public static Book GetBook(this IQueryable<Book> books, string productId)
|
public static Book GetBook(this IQueryable<Book> books, string productId)
|
||||||
|
|||||||
@ -6,25 +6,31 @@ namespace DataLayer
|
|||||||
{
|
{
|
||||||
public static class LibraryQueries
|
public static class LibraryQueries
|
||||||
{
|
{
|
||||||
public static List<LibraryBook> GetLibrary_Flat_WithTracking(this LibationContext context)
|
//// tracking is a bad idea for main grid. it prevents anything else from updating entities unless getting them from the grid
|
||||||
=> context
|
//public static List<LibraryBook> GetLibrary_Flat_WithTracking(this LibationContext context)
|
||||||
.Library
|
// => context
|
||||||
.GetLibrary()
|
// .Library
|
||||||
.ToList();
|
// .GetLibrary()
|
||||||
|
// .ToList();
|
||||||
|
|
||||||
public static List<LibraryBook> GetLibrary_Flat_NoTracking(this LibationContext context)
|
public static List<LibraryBook> GetLibrary_Flat_NoTracking(this LibationContext context)
|
||||||
=> context
|
=> context
|
||||||
.Library
|
.Library
|
||||||
.AsNoTracking()
|
.AsNoTrackingWithIdentityResolution()
|
||||||
.GetLibrary()
|
.GetLibrary()
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
public static LibraryBook GetLibraryBook_Flat_NoTracking(this LibationContext context, string productId)
|
public static LibraryBook GetLibraryBook_Flat_NoTracking(this LibationContext context, string productId)
|
||||||
=> context
|
=> context
|
||||||
.Library
|
.Library
|
||||||
.AsNoTracking()
|
.AsNoTrackingWithIdentityResolution()
|
||||||
.GetLibraryBook(productId);
|
.GetLibraryBook(productId);
|
||||||
|
|
||||||
|
public static LibraryBook GetLibraryBook(this IQueryable<LibraryBook> library, string productId)
|
||||||
|
=> library
|
||||||
|
.GetLibrary()
|
||||||
|
.SingleOrDefault(lb => lb.Book.AudibleProductId == productId);
|
||||||
|
|
||||||
/// <summary>This is still IQueryable. YOU MUST CALL ToList() YOURSELF</summary>
|
/// <summary>This is still IQueryable. YOU MUST CALL ToList() YOURSELF</summary>
|
||||||
public static IQueryable<LibraryBook> GetLibrary(this IQueryable<LibraryBook> library)
|
public static IQueryable<LibraryBook> GetLibrary(this IQueryable<LibraryBook> library)
|
||||||
=> library
|
=> library
|
||||||
@ -32,10 +38,5 @@ namespace DataLayer
|
|||||||
.Include(le => le.Book).ThenInclude(b => b.SeriesLink).ThenInclude(sb => sb.Series)
|
.Include(le => le.Book).ThenInclude(b => b.SeriesLink).ThenInclude(sb => sb.Series)
|
||||||
.Include(le => le.Book).ThenInclude(b => b.ContributorsLink).ThenInclude(c => c.Contributor)
|
.Include(le => le.Book).ThenInclude(b => b.ContributorsLink).ThenInclude(c => c.Contributor)
|
||||||
.Include(le => le.Book).ThenInclude(b => b.Category).ThenInclude(c => c.ParentCategory);
|
.Include(le => le.Book).ThenInclude(b => b.Category).ThenInclude(c => c.ParentCategory);
|
||||||
|
|
||||||
public static LibraryBook GetLibraryBook(this IQueryable<LibraryBook> library, string productId)
|
|
||||||
=> library
|
|
||||||
.GetLibrary()
|
|
||||||
.SingleOrDefault(le => le.Book.AudibleProductId == productId);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,7 +5,6 @@ using Dinah.Core.Net.Http;
|
|||||||
|
|
||||||
namespace FileLiberator
|
namespace FileLiberator
|
||||||
{
|
{
|
||||||
// frustratingly copy pasta from DownloadableBase and DownloadPdf
|
|
||||||
// currently only used to download the .zip flies for upgrade
|
// currently only used to download the .zip flies for upgrade
|
||||||
public class DownloadFile : IDownloadable
|
public class DownloadFile : IDownloadable
|
||||||
{
|
{
|
||||||
|
|||||||
@ -22,11 +22,6 @@ namespace FileLiberator
|
|||||||
return verifyDownload(libraryBook);
|
return verifyDownload(libraryBook);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static StatusHandler verifyDownload(LibraryBook libraryBook)
|
|
||||||
=> !AudibleFileStorage.PDF.Exists(libraryBook.Book.AudibleProductId)
|
|
||||||
? new StatusHandler { "Downloaded PDF cannot be found" }
|
|
||||||
: new StatusHandler();
|
|
||||||
|
|
||||||
private static string getProposedDownloadFilePath(LibraryBook libraryBook)
|
private static string getProposedDownloadFilePath(LibraryBook libraryBook)
|
||||||
{
|
{
|
||||||
// if audio file exists, get it's dir. else return base Book dir
|
// if audio file exists, get it's dir. else return base Book dir
|
||||||
@ -44,6 +39,9 @@ namespace FileLiberator
|
|||||||
return full;
|
return full;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static string getdownloadUrl(LibraryBook libraryBook)
|
||||||
|
=> libraryBook?.Book?.Supplements?.FirstOrDefault()?.Url;
|
||||||
|
|
||||||
private async Task downloadPdfAsync(LibraryBook libraryBook, string proposedDownloadFilePath)
|
private async Task downloadPdfAsync(LibraryBook libraryBook, string proposedDownloadFilePath)
|
||||||
{
|
{
|
||||||
var api = await GetApiAsync(libraryBook);
|
var api = await GetApiAsync(libraryBook);
|
||||||
@ -55,7 +53,9 @@ namespace FileLiberator
|
|||||||
(p) => client.DownloadFileAsync(downloadUrl, proposedDownloadFilePath, p));
|
(p) => client.DownloadFileAsync(downloadUrl, proposedDownloadFilePath, p));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string getdownloadUrl(LibraryBook libraryBook)
|
private static StatusHandler verifyDownload(LibraryBook libraryBook)
|
||||||
=> libraryBook?.Book?.Supplements?.FirstOrDefault()?.Url;
|
=> !AudibleFileStorage.PDF.Exists(libraryBook.Book.AudibleProductId)
|
||||||
|
? new StatusHandler { "Downloaded PDF cannot be found" }
|
||||||
|
: new StatusHandler();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -25,10 +25,7 @@ namespace FileLiberator
|
|||||||
public static LibraryBook GetSingleLibraryBook(string productId)
|
public static LibraryBook GetSingleLibraryBook(string productId)
|
||||||
{
|
{
|
||||||
using var context = DbContexts.GetContext();
|
using var context = DbContexts.GetContext();
|
||||||
var libraryBook = context
|
var libraryBook = context.GetLibraryBook_Flat_NoTracking(productId);
|
||||||
.Library
|
|
||||||
.GetLibrary()
|
|
||||||
.SingleOrDefault(lb => lb.Book.AudibleProductId == productId);
|
|
||||||
return libraryBook;
|
return libraryBook;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -31,6 +31,9 @@ namespace FileManager
|
|||||||
{
|
{
|
||||||
ensureCache();
|
ensureCache();
|
||||||
|
|
||||||
|
if (!tagsCollection.Any())
|
||||||
|
return;
|
||||||
|
|
||||||
// on initial reload, there's a huge benefit to adding to cache individually then updating the file only once
|
// on initial reload, there's a huge benefit to adding to cache individually then updating the file only once
|
||||||
foreach ((string productId, string tags) in tagsCollection)
|
foreach ((string productId, string tags) in tagsCollection)
|
||||||
cache[productId] = tags;
|
cache[productId] = tags;
|
||||||
|
|||||||
@ -13,7 +13,7 @@
|
|||||||
<!-- <PublishSingleFile>true</PublishSingleFile> -->
|
<!-- <PublishSingleFile>true</PublishSingleFile> -->
|
||||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||||
|
|
||||||
<Version>5.4.1.5</Version>
|
<Version>5.4.2.1</Version>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@ -338,7 +338,7 @@ namespace LibationWinForms
|
|||||||
// transform into sorted GridEntry.s BEFORE binding
|
// transform into sorted GridEntry.s BEFORE binding
|
||||||
//
|
//
|
||||||
context = DbContexts.GetContext();
|
context = DbContexts.GetContext();
|
||||||
var lib = context.GetLibrary_Flat_WithTracking();
|
var lib = context.GetLibrary_Flat_NoTracking();
|
||||||
|
|
||||||
// if no data. hide all columns. return
|
// if no data. hide all columns. return
|
||||||
if (!lib.Any())
|
if (!lib.Any())
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user