* Local (eg DbContext.Books.Local): indexes/hashes PK and nothing else. Local.Find(PK) is fast. All other searches (eg FirstOrDefault) have awful performance. It deceptively *feels* like we get this partially for free since added/modified entries live here. * live db: for all importers, fields used for lookup are indexed Using BookImporter as an example: since AudibleProductId is indexed, hitting the live db is much faster than using Local. Fastest is putting all in a local hash table Note: GetBook/GetBooks eager loads Series, category, et al for 1,200 iterations * load to LocalView DbContext.Books.Local.FirstOrDefault(p => p.AudibleProductId == item.DtoItem.ProductId) 27,125 ms * read from live db DbContext.Books.GetBook(item.DtoItem.ProductId) 12,224 ms * load to hash table: Dictionary dictionary[item.DtoItem.ProductId]; 1 ms (yes: ONE) With hashtable, somehow memory usage was not significantly affected ----------------------------------- why were we using Local to begin with? articles suggest loading to Local with context.Books.Load(); this loads this table but not associated fields we want Books and associated fields context.Books.GetBooks(b => remainingProductIds.Contains(b.AudibleProductId)).ToList(); this is emulating Load() but with also getting associated fields from: Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions // Summary: // Enumerates the query. When using Entity Framework, this causes the results of // the query to be loaded into the associated context. This is equivalent to calling // ToList and then throwing away the list (without the overhead of actually creating // the list). public static void Load([NotNullAttribute] this IQueryable source);