Gå til innhold

Anbefalte innlegg

Folkens. Jeg bruker EntityFramework og har klasser som representerer SQL data. gitt følgende klasser

class Kunde
{
   [Key, Column("KundeId")]
   public int Id {get;set;}

   [Column("Navn")]
   public string Navn{get;set;}

}

class KundeInfo
{
   [Key, Column("KundeId")]
   public int Id {get;set;}

   [Column("abc")]
   public int EttElleAnnet{get;set;}
}

 

Kort fortalt er da dette to datasett som skal smeltes sammen i et record set. Jeg prøvde ganske så freidig følgende:

class Kunde
{
   [Key, Column("KundeId")]
   public int Id {get;set;}

   [Column("Navn")]
   public string Navn{get;set;}

   [ForeignKey("Id")]
   public KundeInfo UtvidetInfo{get;set;}
}

Tilsynelatende burde dette gi en utvidelse av klassen Kunde, men under kjøring så feiler det med følgende feilmelding:

 

One or more validation errors were detected during model generation:

 

System.Data.Edm.EdmAssociationEnd: : Multiplicity is not valid in Role 'Internal_LicenseCustomer_LicenseCustomer_Source' in relationship 'Internal_LicenseCustomer_LicenseCustomer'. Because the Dependent Role refers to the key properties, the upper bound of the multiplicity of the Dependent Role must be �1�.

 

Jeg er veldig usikker på hva denne feilmeldingen betyr. Noen som vet hva dette kan være og hvorfor det ikek virker...

Lenke til kommentar
Videoannonse
Annonse

[ForeignKey("Id")]
public KundeInfo UtvidetInfo{get;set;}

 

Er feil. Du kan skrive

 

[Required]
public KundeInfo UtvidetInfo{get;set;}

Da blir relasjonen laget med CASCADE DELETE, eller bare

 

public KundeInfo UtvidetInfo{get;set;}

 

eventuelt

 

[ForeignKey("UtvidetInfo")]
public long KundeInfoId{get;set;}
public KundeInfo UtvidetInfo{get;set;}

eventuelt

public long KundeInfoId{get;set;}
[ForeignKey("KundeInfoId")]
public KundeInfo UtvidetInfo{get;set;}

 

om du absolutt vil angi foreign key spesifikt. Du bruker Code First approach her regner jeg med? Er en del ting som bare funker by convention, så lite du egentlig trenger å angi med mindre du trenger veldig spesifikk funksjonalitet. Et alternativ er å override OnModelBuilder på datacontexten din, så kan du bruke fluent API til å konfigurere hele contexten/databasen der. Personlig foretrekker jeg det om det er veldig mye som må konfigureres.

Endret av The Jackal
Lenke til kommentar

[Required] har ingenting med foreign key å gjøre egentlig. Bare tok det med for å vise en forskjell mellom 1 til 1 og 1 til 0 eller 1 relasjon. Det er det [Required] gjør.

 

Code first er veldig convention basert. Med det mener jeg at hvis du lar propertyene dine ha "riktige" navn, så vil det meste håndteres automagisk for deg. Tenk deg følgende eksempel:

 

public class A
{
 public int Id{get;set;}
 public string SomeProperty{get;set;}
 public List<B> Bs{get;set;}
}
public class B
{
 public int Id{get;set;}
 public string SomeProperty{get;set;}
 public A A{get;set;}
}

 

I dette eksempelet vil alt fungere automagisk som en 1 til 0 eller mange fordi:

-det er en property i hver klasse som heter Id, de vil bli primary key. De kunne også vært kalt AId og BId.

-Collection i klasse A heter det samme som klassenavnet (B) pluss s for at det skal være mange.

-I klasse B blir det blir det samme prinsippet for linken tilbake til A. Implisitt mener jeg å huske at A på klassen B blir automatisk [Required]

 

Mener i alle fall at dette er noenlunde riktig. Min egen lille regel er egentlig at jeg ikke legger på noen som helst attributter med mindre jeg ser at jeg trenger en litt annen funksjonalitet.

 

Legger ved et par eksempler på samme kode som vil gi samme resultat:

public class A
{
 public int Id{get;set;}
 public string SomeProperty{get;set;}
 public List<B> Bs{get;set;}
}
public class B
{
 public int Id{get;set;}
 public string SomeProperty{get;set;}
}

public class A
{
 public int Id{get;set;}
 public string SomeProperty{get;set;}
 public List<B> Bs{get;set;}
}
public class B
{
 public int Id{get;set;}
 public string SomeProperty{get;set;}
 public int AId{get;set;} //implisitt foreign key. For å gjøre denne optional, altså 0 eller 1, så la den være av typen int? (nullable int). Usikker på om det vil gi noen mening egentlig, men men)
 public A A{get;set;}
}

public class A
{
 public int AId{get;set;} //Id og klassenavn + Id er lov for primary key
 public string SomeProperty{get;set;}
 public List<B> Bs{get;set;}
}
public class B
{
 public int BId{get;set;} //Id og klassenavn + Id er lov for primary key
 public string SomeProperty{get;set;}
 public A A{get;set;}
}

Endret av The Jackal
Lenke til kommentar

Glimrende eksempler, men det er fortsatt noe uklart. La oss ta eksemplet ditt:

 

public class A
{
 public int Id{get;set;}
 public string SomeProperty{get;set;}
 public List<B> Bs{get;set;}
}
public class B
{
 public int Id{get;set;}
 public string SomeProperty{get;set;}
 public A A{get;set;}
}

 

Du sier at dette vil fungere. Men hvordan kan det virke? Det er jo ikke definert noe som helst regel for hva B.A skal bruke. Oversatt vil vel dette lage et SQL select statement noe ala dette:

 

SELECT * from A where A.Id = ??

Hva blir puttet in her? Bør kansje legge til at denne relasjonen ikke eksisterer på SQL siden hos oss. Desverre er databasen relativt dårlig beskrevet fordi det er en konvertert flatfil database der alle constraints ligger i programvaren til programmet som er skrevet rundt dette. Gammelt program altså. Jeg lager nye komponenter til programmet og ønsker å kode minst mulig og håpet derfor EF var veien.

Lenke til kommentar

Glimrende eksempler, men det er fortsatt noe uklart. La oss ta eksemplet ditt:

 

public class A
{
 public int Id{get;set;}
 public string SomeProperty{get;set;}
 public List<B> Bs{get;set;}
}
public class B
{
 public int Id{get;set;}
 public string SomeProperty{get;set;}
 public A A{get;set;}
}

 

Du sier at dette vil fungere. Men hvordan kan det virke? Det er jo ikke definert noe som helst regel for hva B.A skal bruke. Oversatt vil vel dette lage et SQL select statement noe ala dette:

 

SELECT * from A where A.Id = ??

Hva blir puttet in her? Bør kansje legge til at denne relasjonen ikke eksisterer på SQL siden hos oss. Desverre er databasen relativt dårlig beskrevet fordi det er en konvertert flatfil database der alle constraints ligger i programvaren til programmet som er skrevet rundt dette. Gammelt program altså. Jeg lager nye komponenter til programmet og ønsker å kode minst mulig og håpet derfor EF var veien.

 

Code first genererer i utgangspunktet databasen for deg. Akkurat hvordan DbContext klassen genererer databasen ut i fra dette vet jeg forsåvidt ikke, men vil tippe det er noen for reflection. Det som nok i alle fall skjer, er at den vil inspisere alle DbSetene du har satt i context klassen din. Altså den som vil se ut noe slikt som dette:

 

public class MyContext : DbContext
{
 public MyContext()
 {
   Database.SetInitializer<MyContext>(null); //Hvis du ikke vil lage en database
 }
 public DbSet<A> As{get;set;}
 public DbSet<B> Bs{get;set;}

 public override void OnModelCreating(ModelBuilder builder)
 {
   //Her kan du bruke fluent API
   base.OnModelCreating(builder);
 }
}

 

Om du faktisk har en database fra før av, må du sørge for å ikke generere databasen (noe EF Code First i utgangspunktet vil gjøre). Da er det naturligvis litt mer hazzle med mapping mellom tabellene i den eksisterende databasen. Er vel kanskje ikke så fullgodt svar dette her, men det bare funker om du gjør det riktig. Står en del om det her: Conventions

 

Du bør kanskje ta en kikk på Entity Framework Database first approach siden du har en database fra før av. Personlig ganske fan av code first, men om du ikke har noe kontroll av hva som kan gjøres med databasen, er det som sagt litt hazzle med code first.

Endret av The Jackal
Lenke til kommentar

Tja...siden du driver å koder klassene dine selv, så virker det som om du har begynt med code first approach. Entity Framework kan brukes på 3 måter, og det vil ha veldig forskjellig sluttresultat:

- Code First

- Model eller database first

 

Fluent API er noe du kun bruker når du bruker code first. Det er istedetfor eller i tillegg til attributter. Du bruker det ikke ved model eller database first. Akkurat hva du skal velge, er ikke alltid helt gitt. Kommer litt an på hva som er tenkt på i framtiden. Code First er vel det som kanskje er mest fleksibelt, men mest jobb. Så om tanken er at dette skal leve lenge, og databasen etterhvert skal forbedres, så kan dette være en mulighet. Om databasen blir det samme, kan du bruke database first og rett og slett få generert alle klassene dine for deg på under 5 minutter.

Lenke til kommentar

Opprett en konto eller logg inn for å kommentere

Du må være et medlem for å kunne skrive en kommentar

Opprett konto

Det er enkelt å melde seg inn for å starte en ny konto!

Start en konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
  • Hvem er aktive   0 medlemmer

    • Ingen innloggede medlemmer aktive
×
×
  • Opprett ny...