← Område 6 Prov 4 · Vad provet prövar Repetition

Webbserverprogrammering 1 · område 6 · lektion 47–48

Vad prov 4 prövar

Osäkerhet inför ett prov kostar mer än innehållet. Den här sidan säger vad som kommer, vad som inte kommer, och hur frågorna ser ut. Två av frågetyperna har kod i sig – exemplen nedan är körda.

1. Formen

2. Vad som kommer

OmrådeUngefärTypiskt innehåll
Code-first och attribut1 frågaVad attributen blir i databasen, och vad de bara blir i formuläret
Migrationer och relationer2 frågorBefintliga rader och en ny främmande nyckel, ON DELETE CASCADE, Include
CRUD och formulär3 frågorÄndringssidans fällor, varför borttagning inte sker på en GET
LINQ2 frågorNär frågan går till databasen, och vad som görs där och vad som görs i C#
Validering3 frågorDe tre sorterna, och i vilken ordning de körs
Inloggning och behörighet3 frågorDölja mot skydda, hashning, antiforgery
Renderingslägen och lagren2 frågorVarför knapparna inte gör något, varför ingen DbContext i en komponent

Det här kommer säkert: vad en migration är och varför den inte redigeras för hand. De tre egenskaperna i en relation, och vad Include gör. Skillnaden mellan att dölja en länk och att skydda en sida. Varför lösenord hashas. Och varför knapparna i en QuickGrid inte gör något under statisk rendering.

Det här kommer inte: inga felmeddelanden att kunna utantill – men du ska kunna säga vad som saknas. Ingen SQL att skriva själv, bara att läsa. Inget om driftsättning eller API:er – det är område 8.

Frågor som frågar var vill ha ett ställe och ett skäl

Var görs urvalet? Var hör regeln hemma? Ett ställe utan skäl ger halva poängen. Svaret ska innehålla ett för att, och gärna ett annars.

3. Frågetyp 1 – läs koden: vad hände här?

Koden bygger. Den gör fel sak. Du ska säga vad som händer, och vad som saknas.

@page "/provtraning/o6/1"
@inject IFilmService Arkivet

@* Provträning till prov 4, frågetyp 1: vad hände här? *@

<h1>Provträning 1</h1>

<ul>
    @foreach (var film in sidan)
    {
        <li>@film.Titel</li>
    }
</ul>

<p>Sida @Sida av @antalSidor</p>

@code {
    [SupplyParameterFromQuery(Name = "sida")]
    public int? Sida { get; set; }

    private List<Film> sidan = new();
    private int antalSidor;

    protected override async Task OnParametersSetAsync()
    {
        List<Film> alla = await Arkivet.HamtaAllaAsync();
        antalSidor = (int)Math.Ceiling(alla.Count / 2.0);

        int nummer = Sida ?? 1;
        sidan = alla.Skip((nummer - 1) * 2).Take(2).ToList();
    }
}

Frågan: vad står på sidan för adresserna nedan? Och vad borde koden ha gjort med sidnumret?

AdressVad står på sidan?
/provtraning/o6/1?sida=2
/provtraning/o6/1?sida=99
/provtraning/o6/1?sida=abc
Vad som ger poäng

?sida=2 ger andra sidan: Rosemarys baby och Såsom i en spegel, och Sida 2 av 3. ?sida=99 ger en tom lista och Sida 99 av 3 – inget fel, bara en sida som inte finns. ?sida=abc ger en 500, och den kommer innan en enda rad av koden körts: ramverket försöker göra om abc till ett int? och misslyckas.

Full poäng kräver det andra ledet: sidnumret kommer ur adressen, och adressen kan vem som helst skriva. Det ska läsas som text, tolkas med int.TryParse och hållas mellan 1 och sista sidan – som i guidens steg 2.

4. Frågetyp 2 – läs frågan: vad blir SQL:en?

Du får en LINQ-fråga och ska säga vad som görs i databasen och vad som görs i C#. Du skriver ingen SQL själv.

using Filmarkivet.Data;
using Microsoft.EntityFrameworkCore;

namespace Filmarkivet.Services;

// Provträning till prov 4, frågetyp 2: vad blir SQL:en?
public class Topplista
{
    private readonly IDbContextFactory<FilmarkivetContext> _fabrik;

    public Topplista(IDbContextFactory<FilmarkivetContext> fabrik)
    {
        _fabrik = fabrik;
    }

    public async Task<List<string>> HamtaAsync()
    {
        using var db = await _fabrik.CreateDbContextAsync();

        return await db.Filmer
            .Where(f => f.Betyg == 5)
            .OrderBy(f => f.LangdMinuter)
            .Select(f => f.Titel)
            .ToListAsync();
    }
}

Frågan: vilka kolumner hämtas ur databasen? Var görs urvalet, och var görs sorteringen? I vilken ordning kommer titlarna, med Filmarkivets frödata?

Vad som ger poäng

Allt görs i databasen, för att allt ligger på frågan före ToListAsync. Bara en kolumn hämtas – Titel – för att Select står före ToListAsync. SQL:en är:

SELECT "f"."Titel"
FROM "Filmer" AS "f"
WHERE "f"."Betyg" = 5
ORDER BY "f"."LangdMinuter"

Filmerna med betyg 5 är Nyckeln till frihet (142 minuter), Sju samurajer (207) och Gökboet (133), och de kommer i längdordning: Gökboet, Nyckeln till frihet, Sju samurajer.

Ett vanligt halvsvar är att Where görs i databasen men Select i C#. Titta på var ToListAsync står – det är där frågan går iväg, och allt före den blir SQL.

5. Frågetyp 3 – placera regeln

Du får en regel och ska säga var den hör hemma: ett attribut, IValidatableObject, eller en kontroll mot databasen. Och varför.

Regeln i FilmarkivetVar?
Längden är mellan 1 och 500 minuter
En film med betyget 5 måste ha en beskrivning
Två filmer får inte ha samma titel och samma år
Utgivningsåret får ligga högst två år fram i tiden

Svara för dig själv innan du klickar på raderna nedan.

RegelnVar, och varför
Längden 1–500 minuterAttribut. Ett fält, en fast gräns. [Range].
Betyg 5 kräver beskrivningIValidatableObject. Två fält tillsammans. Varken betyget eller beskrivningen är fel för sig.
Samma titel och årMot databasen. Kräver att man vet vad som redan finns.
Högst två år framEget attribut. Ett fält – men gränsen beror på vilket år det är, och ett attributs argument måste vara en konstant. Därför inte [Range].

6. Frågetyp 4 – motivera valet

Ingen kod att läsa. Du får ett val och ska säga varför det är rätt, eller vad som hade gått fel med ett annat. Så här kan det se ut:

Frågan

Filmarkivets sökning görs i databasen, men sorteringen i administrationens listvy görs i C#. Varför inte samma ställe för båda?

Vad som ger poäng

Sökningen ska fungera också när arkivet är stort, och då ska databasen välja ut raderna i stället för att allt hämtas. Sorteringen ska vara rätt på svenska, och SQLite sorterar gemener efter alla versaler och Ä före Å. Listan är liten, så det kostar lite att sortera den i C#.

Ett svar som bara säger "det är snabbare" ger inga poäng – snabbare för vad, och varför? Full poäng kräver att båda ställena motiveras var för sig.

Fler frågor av samma sort, att öva på:

7. Sexton repetitionsfrågor

Svara högt för dig själv innan du klickar på raden. Att känna igen ett svar är inte samma sak som att kunna det.

FrågaSvar
Vad blir [StringLength(100)] i en SQLite-tabell?Ingenting. Kolumnen blir TEXT utan längd. Attributet gäller bara i formuläret.
Vad är en migration?En genererad beskrivning av hur databasen ska ändras, räknad fram ur skillnaden mot förra migrationen.
Varför redigeras en migration inte för hand?Den är genererad ur modellen. Ändras den för hand stämmer den inte längre med klassen, och nästa migration räknas fram mot fel utgångsläge. Rätt väg är migrations remove och en ny.
Vilka tre egenskaper har en en-till-många-relation, och vilken blir en kolumn?Den främmande nyckeln och navigationsegenskapen på den ena sidan, listan på den andra. Bara den främmande nyckeln blir en kolumn.
Varför avbryts en migration med en ny obligatorisk främmande nyckel, på en databas med egna rader?De egna raderna får 0 i den nya kolumnen, och det finns ingen kategori med id 0. HasDefaultValue med ett id som finns löser det.
Vad betyder ON DELETE CASCADE?Tas kategorin bort, tas alla dess poster bort också.
Varför är navigationsegenskapen null, fast den främmande nyckeln har ett värde?Den fylls inte av sig själv. Den måste beställas med Include, och glöms det blir det inget fel – bara tomt.
Varför ??= och inte = på ändringssidan?Vid POST har ramverket redan fyllt objektet ur formuläret. = hämtar det gamla ur databasen ovanpå, och ändringen försvinner.
När går en IQueryable till databasen?När den körs – vid ToListAsync, FirstOrDefaultAsync, CountAsync och liknande. Allt före det bygger bara på frågan.
Varför hittar sökningen i databasen inte alltid svenska ord med andra versaler?SQLite viker bara A–Z mellan versaler och gemener. Ä och ä är två olika tecken för den.
Vilka tre sorters validering finns, och vad ser var och en?Attribut ser ett fält. IValidatableObject ser hela objektet. En kontroll mot databasen ser det som redan finns.
Varför körs inte Validate när ett attribut redan sagt nej?Den körs bara på ett objekt vars fält var för sig är giltiga. Det är ingen mening att jämföra två fält om ett av dem är trasigt.
Vad är skillnaden mellan AuthorizeView och [Authorize]?AuthorizeView bestämmer vad som visas. [Authorize] bestämmer vad som går att nå – servern stoppar förfrågan innan sidan körs.
Varför lagras inte lösenordet?Det hashas: görs om till något som går att jämföra med men inte att räkna tillbaka. Den som stjäl databasen får inte lösenorden.
Skyddar <AntiforgeryToken /> i ett formulär till en egen endpoint?Bara om endpointen kontrollerar token. Blazors sidor och EditForm gör det själva, app.MapPost gör det inte.
Varför körs OnInitializedAsync två gånger på en interaktiv sida?Förrendering. Sidan renderas först statiskt i ett objekt som slängs, och byggs sedan om i ett nytt objekt i kretsen.
Den bästa förberedelsen

Gör klart Projekt 1. Provet frågar om exakt det du bygger där – och den som själv sett ändringen försvinna med = behöver inte plugga på den frågan.