/// <summary> /// Merges the changes from a single read-in bookmarkfile into the local database. /// </summary> /// <param name="bmf"></param> /// <returns></returns> private static async Task <int> MergeAsync(BookMarkFile bmf) { int nchanges = 0; // Now let's be very smart about combining this file in with the original. var bookdb = BookDataContext.Get(); var currbooks = CommonQueries.BookGetAllWhichHaveUserData(bookdb); const int CHANGES_PER_SAVE = 1000; int nextDbSaveChange = CHANGES_PER_SAVE; foreach (var external in bmf.BookMarkList) { var book = currbooks.Find(b => b.BookId == external.BookId); if (book == null) { book = CommonQueries.BookGet(bookdb, external.BookId); } if (book == null) { // Prepend the BookMarkSource so that the book is clearly labeled // as being from a bookmark file (and therefore this is kind of a fake entry) if (!external.BookSource.StartsWith(BookData.BookSourceBookMarkFile)) { external.BookSource = BookData.BookSourceBookMarkFile + external.BookSource; } // Must set all these ids to zero so that they get re-set by EF. if (external.Review != null) { external.Review.Id = 0; } if (external.Notes != null) { external.Notes.Id = 0; foreach (var note in external.Notes.Notes) { note.Id = 0; } } if (external.NavigationData != null) { external.NavigationData.Id = 0; } external.DownloadData = null; // on this computer, nothing has been downloaded. CommonQueries.BookAdd(bookdb, external, CommonQueries.ExistHandling.IfNotExists); nchanges++; App.Error($"NOTE: adding external {external.BookId} name {external.Title}"); } else { // Great -- now I can merge the UserReview, Notes, and BookNavigationData. int nbookchanges = 0; if (external.Review != null) { if (book.Review == null) { external.Review.Id = 0; // clear it out so that EF will set to the correct value. book.Review = external.Review; nbookchanges++; } else { nbookchanges += book.Review.Merge(external.Review); } } if (external.NavigationData != null) { if (book.NavigationData == null) { external.NavigationData.Id = 0; // clear it out so that EF will set to the correct value. book.NavigationData = external.NavigationData; nbookchanges++; } else { nbookchanges += book.NavigationData.Merge(external.NavigationData); } } if (external.Notes != null) { if (book.Notes == null) { // Copy them all over book.Notes = new BookNotes() { BookId = external.Notes.BookId, }; foreach (var note in external.Notes.Notes) { note.Id = 0; // reset to zero to insert into the currrent book. book.Notes.Notes.Add(note); } nbookchanges++; } else { // Add in only the changed notes. The ids will not be the same nbookchanges += book.Notes.Merge(external.Notes); } } if (nbookchanges > 0) { ; // hook to hang the debugger on. } nchanges += nbookchanges; if (nchanges > nextDbSaveChange) { await bookdb.SaveChangesAsync(); nextDbSaveChange = nchanges + CHANGES_PER_SAVE; } } } // And save at the end! if (nchanges > 0) { await bookdb.SaveChangesAsync(); } return(nchanges); }