Opgave: Generic DBService and Other refactorings


I denne opgave tager vi udgangspunkt i eksemplet ItemsRazor ItemRazorV9.zip





Opgaven går ud på at gøre DbService generisk (eller refaktoreres, hvis den allerede er generisk)
samt at implementere diverse mindre opdateringer til applikationen.


Step 1 (Models - Item)
I class Item er property Price af typen double og der er en begrænsning på længden af Name på 30 karakterer.

  1. Ændre typen af Price fra double til decimal.
  2. Ændre DataAnnotation på NameStringLength bliver 100 (i stedet for 30)
  3. Kør Add-Migration og Update-database i PMC'en
  4. Genindlæs evt data fra Json-filen (nu skulle alle Items gerne komme med).

I opgaven: CookieAuthenticationItems blev der i LogInPagecshtml.cs benyttet en static property LoggedInUser af typen User til at referere til den user der er logget ind.
Det havde den konsekvens, at der kun kunne vises en User som "current user" i menuen (_Layout.cshtml). Selv om flere Usere var logget på systemet vises samme bruger alle steder
(også selv om der benyttes forskellige browsere, der ikke har samme cookies!)


Step 2 ( LogInPage.cshtml.cs)


Step 3 ( _Layout.cshtml)

Opdater filen så der ikke refereres til den statiske LogInPageModel.LoggedInUser, men istedet til Context.User.Identity og Context.User.Identity.Name der indeholder UserName på den bruger der er logget ind.

Bemærk:
I LogInPage oprettes et Claim med ClameTypes.Name der har value: UserName. Dette Claim gives til ClaimsIdentity og sendes videre iforb med SingIn. Derfor er UserName tilgængelig via Context.User.Identity.Name.

 

Step 4 ( LogOutPage.cshtml.cs)


Step 5 (Index.cshtml.cs)

 

Så er vi klar til at gøre DbService generisk og introducere interfacet IService.

Step 6 (IService.cs)
Opret et nyt generisk interface IService<T> i mappen Services med følgende metoder:

Task<IEnumerable<T>> GetObjectsAsync();
Task AddObjectAsync(T obj);
Task DeleteObjectAsync(T obj);
Task UpdateObjectAsync(T obj);
Task<T> GetObjectByIdAsync(int id);


Step 7 (DbGenericService.cs)
Opret en ny generisk klasse DbGenericService der implementere IService:

class DbGenericService<T> : IService<T> where T : class

Bemærk: where T : class sikre at typen T er en klasse.

 

public async Task<IEnumerable<T>> GetObjectsAsync()
{
using (var context = new ItemDbContext())
{
return await context.Set<T>().AsNoTracking().ToListAsync();
}
}

Bemærk: Set<T>() referere til DbSet<Item> eller DBSet<User> afh af T, AsNoTracking() er blot en lille optimering så der ikke trackes på den returnerede liste (den skal ikke opdateres og dermed heller ikke DB)

 

public async Task AddObjectAsync(T obj)
{
using (var context = new ItemDbContext())
{
context.Set<T>().Add(obj);
await context.SaveChangesAsync();
}
}

Bemærk: Der benyttes await og SaveChangesAsync for at sikre asynkron afvikling og at der ikke returneres fra metoden før opdateringen er gennemført.

 

Implementer selv de øvrige metoder.
Hint: FindAsync(id) når der skal returneres et bestemt objekt
Husk: At registrere den nye Service i startup.cs

 

Step 4 (Afprøv)
Afprøv at det refaktorerede program virker.

 

 


God fornøjelse!
Henrik Høltzer