[C#/Linq] selecteer een gerelateerd object met voorkeur

Pagina: 1
Acties:

Onderwerpen


  • Grijze Vos
  • Registratie: December 2002
  • Laatst online: 28-02 22:17
Ik probeer een zinnige linq expressie te bouwen voor het volgende probleem.

Je hebt een tabel X, en een tabel XLocale, waarbij XLocale de velden bevat die in meerdere talen beschikbaar zijn.

Nu wil ik een anonymous object maken die deze twee tabellen samen trekt in een entiteit, waarbij de vertaalde velden van een bepaalde taal moeten worden gekozen, maar mochten die niet bestaan, dan mag een willekeurige andere vertaling gekozen worden.

Ik heb nu de volgende expressie, alleen deze gaat natuurlijk keihard op zn gat als er geen nederlandse vertaling is.

C#:
1
2
3
4
5
var xs = 
  from x in X
  select new {
    x.A, x.B, x.C,
    Name = x.XLocale.Where(xloc => xloc.Language == "nl-NL").Single().Name;


DE O/R mapper die ik gebruik voor de DB access is LLBLGen, alhoewel dat in principe niet van belang zou moeten zijn. Weet iemand een zinnige manier om de expressie te herformuleren zodat hij bij afwezigheid van de nederlandse vertaling een ander kiest? Of is het beter om voor een database view oid te gaan hiervoor?

Op zoek naar een nieuwe collega, .NET webdev, voornamelijk productontwikkeling. DM voor meer info


  • Guldan
  • Registratie: Juli 2002
  • Laatst online: 11-09 19:49

Guldan

Thee-Nerd

Grijze vos,

het is misschien niet helemaal wat je zoekt (en misschien had je deze al gevonden) maar hier staat een voorbeeld van een 'exists' expressie:

http://www.linq-to-sql.co...linq-upgrade/linq-exists/

Ook zou je het misschien wel kunnen doen met een any expressie en a.d.h.v het resultaat (dus als de locale voorkomt) deze gebruiken en wanneer deze niet voorkomt een standaard kiezen. Dus eigenlijk de where dynamisch opbouwen.

You know, I used to think it was awful that life was so unfair. Then I thought, wouldn't it be much worse if life were fair, and all the terrible things that happen to us come because we actually deserve them?


  • pedorus
  • Registratie: Januari 2008
  • Niet online
Wat zou er mis zijn met SingleOrDefault() ?? [andere query] (dus gewoon twee queries doen indien nodig)? Alternatief is inderdaad exists of iets met orderby ofzo. Waarom selecteer je A, B en C om vervolgens alleen de Name op te vragen? :p

Vitamine D tekorten in Nederland | Dodelijk coronaforum gesloten


  • Peelee
  • Registratie: Mei 2010
  • Laatst online: 04-01-2021
Je zou hiervoor gebruik kunnen maken van de null-coalescing operator in c#, bv als volgt:
code:
1
2
3
4
5
var xs = 
  from x in X
  select new {
    x.A, x.B, x.C,
    Name = ( x.XLocale.Where(xloc => xloc.Language == "nl-NL").FirstOrDefault() ?? x.XLocale.FirstOrDefault() ).Name;

Deze werkt als volgt: is
code:
1
x.XLocale.Where(xloc => xloc.Language == "nl-NL").FirstOrDefault()
niet null, dan wordt gewoon die waarde genomen (de nederlandse vertaling). Is die waarde wel null, dan wordt het stuk na de '??' geevalueerd. In dat stuk zoek je dan gewoon de eerste waarde op (zonder filter op 'nl-NL').

Nu kan het ook wel nog steeds zo zijn dat er absoluut geen vertaling is (ook niet in andere talen), en dan faalt deze method nog steeds. Hiervoor kan je bv nog eens de ?? gebruiken om een default XLocale object weer te geven, met bv Name='<not translated>' ofzo

  • Grijze Vos
  • Registratie: December 2002
  • Laatst online: 28-02 22:17
Peelee schreef op donderdag 09 september 2010 @ 12:16:
Je zou hiervoor gebruik kunnen maken van de null-coalescing operator in c#, bv als volgt:
code:
1
2
3
4
5
var xs = 
  from x in X
  select new {
    x.A, x.B, x.C,
    Name = ( x.XLocale.Where(xloc => xloc.Language == "nl-NL").FirstOrDefault() ?? x.XLocale.FirstOrDefault() ).Name;

Deze werkt als volgt: is
code:
1
x.XLocale.Where(xloc => xloc.Language == "nl-NL").FirstOrDefault()
niet null, dan wordt gewoon die waarde genomen (de nederlandse vertaling). Is die waarde wel null, dan wordt het stuk na de '??' geevalueerd. In dat stuk zoek je dan gewoon de eerste waarde op (zonder filter op 'nl-NL').
Thanks! Niet aan gedacht dat de coalesc zou kunnen. Ga het meteen proberen.
Nu kan het ook wel nog steeds zo zijn dat er absoluut geen vertaling is (ook niet in andere talen), en dan faalt deze method nog steeds. Hiervoor kan je bv nog eens de ?? gebruiken om een default XLocale object weer te geven, met bv Name='<not translated>' ofzo
Minstens 1 vertaling wordt in UI afgedwongen, dus da's geen probleem.
pedorus schreef op donderdag 09 september 2010 @ 12:16:
Wat zou er mis zijn met SingleOrDefault() ?? [andere query] (dus gewoon twee queries doen indien nodig)? Alternatief is inderdaad exists of iets met orderby ofzo.
Ik had zo'n gevoel had dat ik over iets ontzettends simpels heen zat te kijken, en dat was ook zo. ;) Dit is natuurlijk de oplossing.
Waarom selecteer je A, B en C om vervolgens alleen de Name op te vragen? :p
In dit specifieke geval ben ik toevallig alleen geinteresseerd in de gelokaliseerde name.


====

De aangedragen oplossing werkte niet helemaal overigens, omdat de SingleOrDefault/FirstOrDefault natuurlijk null kan zijn, een let operator zorgt voor de oplossing. Voor de volledigheid:

C#:
1
2
3
4
5
6
7
var xs = 
  from x in X
  let xLocale = x.XLocale.SingleOrDefault(xloc => xloc.Language == "nl-NL") ?? x.XLocale.First()
  select new {
    x.A, x.B, x.C,
    Name = xLocale.Name
};

[ Voor 30% gewijzigd door Grijze Vos op 09-09-2010 13:48 ]

Op zoek naar een nieuwe collega, .NET webdev, voornamelijk productontwikkeling. DM voor meer info