NHibernate optimaliseren: laad alle gegevens uit opgegeven tabellen

Scenario: I have built an ASP.NET MVC application that manages my cooking recipes. I am using FluentNHibernate to access data from the following tables:

  1. Users
  2. Categories
  3. Recipes
  4. RecipeCategories (many-to-many junction table)
  5. UserBookmarkedRecipes (many-to-many junction table)
  6. UserCookedRecipes (many-to-many junction table)

Question: Is there any way to tell NHibernate to load all data from all tables listed above and store it in memory/in NHibernate's cache so that there do not have to be any additional database requests?


Motivation behind question: The variety of many-to-many relationships poses a problem and would greatly benefit from that optimization.

Note regarding data: The overall amount of data is extremely small. We are talking about less than 100 recipes at the moment.

1

1 antwoord

In plaats van alles vooraf te laden, zou ik voorstellen om eenmaal te laden en het vervolgens vast te houden terwijl het wordt geopend.

NHibernate maintains two different caches, and does a pretty good job of keeping them in sync with your underlying data store. By default, it uses what is called a "first level" cache on a per-session basis but I don't think that's what you want. You can read about the differences at the nhibernate faq page on caching

Ik vermoed dat een cache op het tweede niveau is wat je nodig hebt (dit is overal in je app beschikbaar). U moet een cacheprovider krijgen van NHContrib (download de versie die komt overeen met uw versie van NHibernate). De SysCache2-provider is waarschijnlijk de gemakkelijkste om in te stellen voor uw scenario, zolang uw app het ENIGE is dat naar de database wordt geschreven. Als andere processen zullen schrijven, moet u ervoor zorgen dat iedereen dezelfde cache gebruikt als een tussenpersoon als u wilt dat deze synchroon blijft.

De cache op het tweede niveau is geconfigureerd met een time-out die u kunt instellen op wat u nodig hebt. Denk niet dat het oneindig kan zijn, maar je kunt het instellen op lange perioden als je dat wilt (waarschijnlijk is het geen slecht idee om van tijd tot tijd terug te gaan naar DB). Als u alles van tevoren wilt vooraf laden, kunt u eenvoudig toegang krijgen tot al uw entiteiten via de Application_Start-methode van global.asax, maar dit zou niet nodig moeten zijn.

U moet uw sessiefabriek configureren om de cache te gebruiken. Roep de .Cache-methode (...) aan wanneer u uw sessiefabriek vloeiend configureert. Dit zou relatief vanzelfsprekend moeten zijn.

U moet ook Cache.ReadWrite() instellen in zowel uw entiteitstoewijzingen EN uw relatietoewijzingen. U kunt dit doen volgens conventie of door Cache.ReadWrite() aan te roepen in uw vloeiende toewijzingen.

Zoiets als:

public class RecipeMap : ClassMap {
    public RecipeMap() {
        Cache.ReadWrite();
        Id(x => x.Id);
        HasManyToMany(x => x.Ingredients).Cache.ReadWrite();
    }
}

Op de Cache-aanroepen in uw toewijzingen kunt u ReadOnly specificeren of wat u verder nog nodig heeft. NonStrictReadWrite is interessant, het kan de prestaties aanzienlijk verbeteren, maar met een verhoogd risico op het lezen van verouderde gegevens uit de cache.

2
toegevoegd
Hartelijk dank voor uw gedetailleerde antwoord, ik waardeer de inspanning enorm. Ik heb echter een vraag: voor zover ik je beschrijving van de cache van het eerste niveau op basis van sessie per sessie begreep, zou ik deze cachingmethode meer geschikt achten voor mijn scenario. Gedurende 99% van de tijd is slechts één gebruiker tegelijk ingelogd; om toegang te krijgen tot alle gegevens, moet die gebruiker ingelogd zijn. Bent u na het kennen van mijn aanvraag nog steeds van mening dat de NHContrib SysCache2 meer geschikt is, en zo ja, wat zijn dan de nadelen van de eerste niveau cache?
toegevoegd de auteur Marius Schulz, de bron
Update: Het spijt me, ik heb de term sessie gelezen en dacht aan een ASP.NET-sessie (die zou zijn wat ik wilde bereiken). Ik begrijp nu het verschil, en je hebt gelijk: dat gedrag is niet wat ik probeer te bereiken.
toegevoegd de auteur Marius Schulz, de bron
Precies, ik dacht aan een websessie, geen NH-sessie. Ik accepteer je antwoord zo snel mogelijk!
toegevoegd de auteur Marius Schulz, de bron
Dit is afhankelijk van wat uw strategie voor sessiebeheer is - meestal is in een webapp de levensduur van de sessie één verzoek (denk aan een NH-sessie, geen websessie). Sommige apps krijgen eenvoudigweg een nieuwe sessie per pagina/besturingselement, of zelfs per oproep tot niberiberatie. De cache op het eerste niveau is niet bedoeld om lang te leven, maar om te optimaliseren binnen een enkele werkeenheid. Dus ja, ik denk dat het tweede niveau nog meer geschikt is voor jouw scenario. Ik zou alleen op het eerste niveau vertrouwen voor dit type caching als ik een winforms-app met één sessie zou gebruiken met een ingesloten database zoals SQLite.
toegevoegd de auteur AlexCuse, de bron