[C#] ApplicationUser on cascade delete

Pagina: 1
Acties:

Acties:
  • 0 Henk 'm!

  • ZeroCode
  • Registratie: Februari 2002
  • Laatst online: 06-10 23:13
Na verschillende google en msdn pagina's gelezen te hebben kom ik nog niet helemaal uit on cascade deleting. Ik heb een standard MVC 5 webapp gemaakt in visualstudio en de ApplicationUser class aangepast als volgt:

C#:
1
2
3
4
5
public class ApplicationUser : IdentityUser
{
        public ApplicationUser() { }
        public virtual Naam Naam { get; set; }
}


De Naam class ziet er zo uit:
C#:
1
2
3
4
5
6
7
public class Naam
{
     public int NaamId { get; set; }
     public string Voornaam { get; set; }
     public string Achternaam { get; set; }
     public string Tussenvoegsels { get; set; }
}


De applicationDbContext heb ik aangepast zodat cascade delete aan staat zoals hier weergegeven:
C#:
1
2
3
4
5
6
7
8
9
10
11
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();

    modelBuilder.Entity<Naam>()
                .HasOptional(a => a.User)
                .WithOptionalDependent()
                .WillCascadeOnDelete(true);

    base.OnModelCreating(modelBuilder);
}


Nu had ik verwacht als ik de gebruiker weg zou gooien dat de gerelateerde record in de "Naam" table ook weggegooid zou worden, maar dit is niet het geval.

C#:
1
2
3
4
5
6
var userManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(context));
var currentUser = userManager.FindById(User.Identity.GetUserId());

currentUser.Naam = new Naam() { Voornaam = "Jan", Achternaam = "Jansen", Tussenvoegsels = "" };
userManager.Update(currentUser);
userManager.Delete(currentUser);


Wat ik geprobeert heb is op het model op verschillende manieren aan te maken en alle mogelijke vormen van de migraties heb getest. Ik snap niet wat ik hier verkeerd doe. Een 1 op 1 relatie d.m.v. het Entity Framework hoeft toch niet zo lastig te zijn?

DataAnnotations en Fluent API beide geprobeerd, beide wil hier helaas niet werken.
Daarnaast vroeg ik mij af of het wel een best practice is om de ApplicationUser class uit te breiden of is het verstandiger om een eigen User class te maken welke erft van ApplicationUser.

Acties:
  • 0 Henk 'm!

  • Sebazzz
  • Registratie: September 2006
  • Laatst online: 12-10 15:56

Sebazzz

3dp

Algemeen op je design zou ik op dit moment zeggen dat je een component moet gebruiken en geen 1-op-1 relatie. Een component is een object-georienteerde onderverdeling die uiteindelijk in je tabel wordt opgenomen. Gezien jij een optional principal gebruikt moet je component nullable zijn, ik weet niet zeker of Entity Framework dit reeds aan kan.

Is overigens WithOptionalPrincipal niet geschikter voor jouw doel?
Daarnaast vroeg ik mij af of het wel een best practice is om de ApplicationUser class uit te breiden of is het verstandiger om een eigen User class te maken welke erft van ApplicationUser.
Ligt eraan hoe dit samenvalt met de rollen binnen je applicatie. Bij één van onze applicaties bevat een bepaalde gebruiker dermate veel specifieke informatie dat we daar inheritance gebruiken.

[Te koop: 3D printers] [Website] Agile tools: [Return: retrospectives] [Pokertime: planning poker]


Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
In dit geval zou ik er sowieso voor kiezen om van Naam een ComplexType te maken. Op die manier wordt hij gewoon binnen dezelfde table/record opgeslagen en heb je helemaal geen probleem met cascading deletes.

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • Sebazzz
  • Registratie: September 2006
  • Laatst online: 12-10 15:56

Sebazzz

3dp

Een component dus, maar dat is een NHibernate term :p

[Te koop: 3D printers] [Website] Agile tools: [Return: retrospectives] [Pokertime: planning poker]


Acties:
  • 0 Henk 'm!

  • ZeroCode
  • Registratie: Februari 2002
  • Laatst online: 06-10 23:13
Bedankt voor de informatie, ComplexType had ik inderdaad wel gevonden maar ik wist niet dat het in dezelfde tabel opgeslagen zou worden. Ik ga er even verder over lezen en wat experimenteren.

Wat ik mij nu wel afvraag is stel ik wil een adres bij de ApplicationUser toevoegen, maak ik dan weer een complextype? Op 1 adres kunnen immers meerdere gebruikers bijvoorbeeld wonen.

Ik begrijp uit veel artikelen dat Entity Framework eigenlijk niet zo goed overweg kan met 1op1 relaties. Dat het meer rekent uit 1 op meer relaties.

Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
ZeroCode schreef op dinsdag 25 augustus 2015 @ 18:45:
Wat ik mij nu wel afvraag is stel ik wil een adres bij de ApplicationUser toevoegen, maak ik dan weer een complextype? Op 1 adres kunnen immers meerdere gebruikers bijvoorbeeld wonen.
Dat is een beetje afhankelijk van hoe je je datamodel opstelt. Als je het daadwerkelijk als 1/n relatie wil modeleren dan moet je het dus niet als ComplexType modeleren.

Bedenk je overigens wel of je het echt perse als 1/n relatie wil modeleren. Hoewel het inderdaad zo is dat er meerdere mensen op 1 adres wonen, en het qua normaalvorm puurder is, wil je meestal niet dat je automatisch de adresvelden van andere gebruikers wijzigt. Uiteindelijk is adres dus eigenlijk een immutable object. Qua datastructuur kies ik er dan ook vaak voor om adres gewoon als velden van een persoon op te nemen, en dus inderdaad een complextype te gebruiken.

Zo gauw als je N adressen per persoon gaat krijgen dan zul je dus wel een 1/n of n/n relatie moeten aanleggen. Maar ook daar kies ik er meestal voor om adressen niet voor meerdere personen te hergebruiken. Dus een 1/n relatie, maar dan de andere kant op.
Ik begrijp uit veel artikelen dat Entity Framework eigenlijk niet zo goed overweg kan met 1op1 relaties. Dat het meer rekent uit 1 op meer relaties.
Op zich is een 1-1 relatie natuurlijk gewoon gelijk aan een 1-n relatie. Ik zie ook niet in waarom het entity framework daar niet goed mee om kan gaan. Maar relaties zijn nou eenmaal complexer dan extra velden inladen.
Sebazzz schreef op dinsdag 25 augustus 2015 @ 17:45:
Een component dus, maar dat is een NHibernate term :p
Ik moet bekennen dat ik je post niet echt gelezen had, alleen gescand of je het over een CompexType had ;)

[ Voor 16% gewijzigd door Woy op 25-08-2015 20:03 ]

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • ZeroCode
  • Registratie: Februari 2002
  • Laatst online: 06-10 23:13
Ik kom er niet helemaal uit, ik probeer nu de ApplicationUser uit te breiden met een Person class.
Dus het volgende:
code:
1
public virtual Person Person { get; set; }


Daarnaast maak ik een Person class:
code:
1
2
3
4
5
public class Person
{
      public int PersonID { get; set; }
      public string FirstName { get; set; }
}


Bij het verwijderen word alleen de applicationuser verwijderd in de database. Iemand een idee? Heb echt tig verschillende annotaties gebruikt maar kom er niet uit.

Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Heb je hier gekeken? MSDN: Entity Framework Fluent API - Relationships

Je moet op je EntityDefinitie van je ApplicationUser de relatie naar Person op CascadeOnDelete = true zetten.

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • ZeroCode
  • Registratie: Februari 2002
  • Laatst online: 06-10 23:13
Ja hier heb ik inderdaad al naar gekeken, had het volgende staan:
code:
1
2
3
4
modelBuilder.Entity<ApplicationUser>()
                        .HasRequired(t => t.Persoon)
                        .WithOptional(t => t.ApplicationUser)
                        .WillCascadeOnDelete(true);


Daarnaast heb ik het ook geprobeerd via dataannotations, als laatste probeerde ik
code:
1
2
[Required]
public virtual Person Person { get; set; }


Ik zit echt nogal vast, snap er geen niks van. Iets dat zo simpel is dat het mij zoveel tijd kost. Ik doe echt iets enorm fout.

Het is dus echt een lege MVC applicatie waar ik een normale class aan probeer te koppelen.

[ Voor 7% gewijzigd door ZeroCode op 02-09-2015 21:31 ]


  • mulder
  • Registratie: Augustus 2001
  • Laatst online: 16:21

mulder

ik spuug op het trottoir

Hebben de tabellen überhaupt relaties in de database? Zijn het geen losse tabellen?

oogjes open, snaveltjes dicht


  • Jogai
  • Registratie: Juni 2004
  • Laatst online: 22:22
Volgens mij moet je het zo doen in je person class:
C#:
1
2
3
        public int UserId { get; set; }

        public virtual ApplicationUser User { get; set; }

En de configuratie zo:
C#:
1
2
3
            HasRequired(c => c.User)
                .WithMany()
                .HasForeignKey(c => c.UserId);

Oftewel je mist de primary key naar je applicationuser in person.

Klik hier om op linkedIn lid te worden van de Freelance Tweakers groep.


  • FeronIT
  • Registratie: Mei 2015
  • Laatst online: 09-10 21:00
Een beetje wat @mulder zegt. De database moet de cascade-delete actie uitvoeren. Hiervoor moeten deze tabellen een FK relatie hebben en op die relatie moet de cascade delete aangevinkt zijn.

Acties:
  • 0 Henk 'm!

  • ZeroCode
  • Registratie: Februari 2002
  • Laatst online: 06-10 23:13
Het is mij uiteindelijk gelukt, ik deel gelijk de code even:

Dit heb ik gebruikt in de ApplicationUser class:
code:
1
2
3
4
public class ApplicationUser : IdentityUser
{
     public virtual Persoon Persoon { get; set; }
}


het volgende bij de OnModelCreating:
code:
1
2
3
4
5
6
7
8
9
10
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
    modelBuilder.Entity<Persoon>()
        .HasRequired(m => m.User)
        .WithOptional(m => m.Persoon)
        .Map(m => { m.MapKey("UserId"); })
        .WillCascadeOnDelete(true);
    base.OnModelCreating(modelBuilder);
}


En in de class Persoon het volgende als Primary key:
code:
1
2
3
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }


en een navigatie property:
code:
1
public virtual ApplicationUser User { get; set; }


Nu werkt de cascade zoals verwacht. Bedankt voor alle hulp!

[ Voor 0% gewijzigd door ZeroCode op 04-09-2015 20:51 . Reden: Curly stond verkeerd ]

Pagina: 1