Avatar billede CodingJoe Nybegynder
21. december 2010 - 00:43 Der er 39 kommentarer og
1 løsning

LINQ problermer med en where med en enum

Jeg bruger Linq2Sql og forsøger at lave en where med enum værdi:

string filter = "en_vaerdi";
).Where(l.MinEnum == filter)).OrderByDescending...

Jeg har forsøgt med en:
l.MinEnum.ToString() == filter

Men får denne fejl:
Method 'System.Object Parse(System.Type, System.String)' has no supported translation to SQL.

Omvendt har jeg også forsøgt at caste mit filter til MinEnum...men det virker heller ikke. Jeg har søgt på nettet, men ikke fundet et hit omkring mit problem overhovedet.

Nogen herinde der kan hjælpe, så jeg kan komme i seng :)
Avatar billede Syska Mester
21. december 2010 - 09:14 #1
.Where(l => l.MinEnum == filter);

MinEnum går jeg ud fra er en string.

"=>" skal forstås som "goes to", dvs at "l" bliver en place holder for værdier i listen ....

mvh
Avatar billede janus_007 Nybegynder
21. december 2010 - 09:30 #2
Din enum findes ikke i databasen, derfor brokker den sig over at den ikke kan oversætte.
Jeg forstår ikke hvad en enum gør der?

Brug feltnavne istedet :)

string filter = "en_vaerdi";
).Where(l.SomeField == filter)).OrderByDescending...
Avatar billede janus_007 Nybegynder
21. december 2010 - 09:31 #3
syntax error....
string filter = "en_vaerdi";
).Where(l => l.SomeField == filter)).OrderByDescending...
Avatar billede CodingJoe Nybegynder
21. december 2010 - 09:45 #4
Det er fordi jeg lægger mine db data ind i mit domæne entitet i samme linq udtryk...det kan være jeg skal smide hele mit linq udtryk ind...istedet for et udpluk af det...det gør jeg, når jeg kommer hjem.
Avatar billede Syska Mester
21. december 2010 - 09:49 #5
Super ... :-)

Ja, det vil gøre det meget nemmere for os.

Men som janus også så fint har sagt, så har du en syntax error, som jeg også har beskrevet i mit første indlæg.

Måske det er gået lidt for stærkt i går :-)

mvh
Avatar billede CodingJoe Nybegynder
21. december 2010 - 15:12 #6
Nej, udtrykket virker fint uden enum. Jeg har sågar andre værdier jeg foretager et tjek på uden problemer.

Jeg kan godt se, der er en syntaks fejl. Deraf en fejl i koden. Spørgsmålet går på at finde ud af, hvordan man behandler en where med en enum i et linq udtryk.

Jeg prøver jeres foreslag, når jeg engang er hjemme.
Avatar billede CodingJoe Nybegynder
21. december 2010 - 17:00 #7
Så vidt jeg kan se, så er det syntaks error på din måde buzzz.
Avatar billede Syska Mester
21. december 2010 - 17:14 #8
Post nu noget kode ... vi kan ikke gætte os frem.

Gerne DB Struktur, da jeg ikke er klar over hvordan du har fået Enum support i linq2sql. Sidst jeg brugte det var der nemlig ikke.

Post gerne ekstra meget info ... :-)

mvh
Avatar billede CodingJoe Nybegynder
21. december 2010 - 17:44 #9
Det er faktisk det, der er problemet...Der er ingen support på enum i LinqToSql.

List<MyObject> myObjects;
            using (var context = new MyDataContext(ConfigurationManager.ConnectionStrings["MyConnection"].ConnectionString)) {
                myObjects = context.MyTable.Select(l => new MyObject {
                    Id = l.ID, Date = l.Timestamp, Category = (Category)Enum.Parse(typeof(Category), l.Category),
                    FieldName = l.FieldName, AnotherName = l.AnotherName, PId = Convert.ToInt64(l.PID),
                    ThreadName = l.ThreadName}).Where(l => l.Date >= dateRangeSet.From && l.Date <= dateRangeSet.To && l.Category == myCategory)).OrderByDescending(l => l.Date).ToList();
            }
            return myObjects;

Problemet opstår som sagt i min where clause....min enum map i det tidligere virker uden problemer...

Jeg har snakket med en på arbejde, han har givet mig et forslag jeg lige vil prøve...
Avatar billede CodingJoe Nybegynder
21. december 2010 - 17:46 #10
Ingen grund til en db struktur. Feltet er et varchar felt, og jeg henter data fra samme tabel.
Avatar billede CodingJoe Nybegynder
21. december 2010 - 17:48 #11
Avatar billede Syska Mester
21. december 2010 - 17:55 #12
Ja, men så har du jo heller ikke givet os nok information til at starte med.

1. Kunne ikke compile pga forkert syntax i din Where clause.

Jeg ville nok gemme min Enum i DB som et tal ... og i din kode:

enum SomeEnum
{
Type1 = 1,
Type2 = 2,
TypeX = 10,
}

På den må har du altid en mapning mellem dem, og du er ikke hængt op på navnet, men et tal ... som man alligevel er et eller andet sted med enums.

Men godt til kom til at virke, selvom vi ikke kunne bibrage med meget.

mvh
Avatar billede Syska Mester
21. december 2010 - 17:57 #13
Netop grund til DB struktur, da vi ellers kun kan gætte hvad du prøver på ... jeg havde nemlig forventet din Enum værdi i databasen var en tal.

Din første kode, viste dog måske tegn på at det kunne være en string, da du prøvede med en Where syntax til en string: filter

Men altså ... godt det kom til at virke.
Avatar billede CodingJoe Nybegynder
21. december 2010 - 17:59 #14
Ja, beklager det var en:
l.Category.ToString() == myCategory

Jeg havde forsøgt med...
Avatar billede d3crypt0 Nybegynder
21. december 2010 - 18:20 #15
Er ret ny herinde...men kan se du kan bruge dette.

Som du helt rigtigt har nævnt er Enum desværre ikke understøttet i det nuværende LinqToSql. Desværre fikser MS heller ikke dette problem i deres næste opdatering.

Det du meget hurtigt kan gøre er følgende:

- Åbn din *.dbml i en text editor.
- Lokalisér dit "enum" felt, som sikkert i dette tilfælde er af typen System.string. Erstat dette med dit enum med det fulde navn dvs. med namespace fx: MitNamespace.MineEnums.MitEnum.
- Gem dette og skriv -> Category = l.Category...
- I din where (hvor problemet startede) skriver du herefter blot:
l.Category.ToString() == myCategory

Sig til hvis du har andre problemer...
Avatar billede CodingJoe Nybegynder
21. december 2010 - 18:28 #16
Jeg er imponeret...det virker sgu :D
Jeg havde ikke engang brug for prøve det min kollega havde givet som forslag.

Det virker dog som et hack...noget jeg bør tænke over ved denne løsning?
Avatar billede d3crypt0 Nybegynder
21. december 2010 - 18:31 #17
Ja, det er desværre et hack, da enum ikke er supporteret. Jeg er dog ikke så bekymret over dette, da dbml filen er autogenereret. Hvis du laver en opdatering af det, så ryger dit felt tilbage til en string type. Det er det eneste, du skal være klar over.
Avatar billede CodingJoe Nybegynder
21. december 2010 - 18:32 #18
Det er noteret...smider du et svar ind...så er der point :)
Avatar billede d3crypt0 Nybegynder
21. december 2010 - 18:35 #19
Her er et svar.
Avatar billede Syska Mester
21. december 2010 - 18:42 #20
Og hvad gør den så når du laver en query på den ?
Avatar billede CodingJoe Nybegynder
21. december 2010 - 18:52 #21
Den finder kun de resultater, hvor kategorien er lig med min enum streng værdi...det virker uden problemer.
Avatar billede janus_007 Nybegynder
21. december 2010 - 20:38 #22
Jeg synes det er en meget skidt idé at redigere i en autogenereret fil som eks.vis dbml. Pludselig sidder man efter nogle måneder og har glemt alt om det og så skal man lige opdatere noget og vupti er koden væk og man kan intet huske.
Avatar billede d3crypt0 Nybegynder
21. december 2010 - 22:14 #23
Jeg synes autogenererede filer er noget skrammel i det hele taget, så man er vel lige vidt. Microsoft har kendt til dette problem i et stykke tid. Den indkopierede kode har opbygning, der er struktureret korrekt. Den anden løsning ville være at behandle rå-data først og herefter mappe dem, hvilket ville være en smule mere omstændigt.

Bliver koden tjekket ind i source control med en tilsvarende beskrivende kommentar, ser jeg ikke noget problem, ligesom alt andet alligevel kan være glemt undervejs. Men det er et lille hack, som jeg har skrevet tidligere.
Avatar billede Syska Mester
21. december 2010 - 22:38 #24
Men hvad værdi har man af den Enum hvis man alligevel sammenligner med en string?

Hvad formål har det så tjent ? Udover intet ...

mvh
Avatar billede d3crypt0 Nybegynder
21. december 2010 - 22:51 #25
Det må du spørge CodeJoe om. I hans tilfælde bliver Enum sikkert brugt til at holde på en standardiserede logiske tekst enheder, hvilket er helt legalt. Som default falder en Enum ellers tilbage til en int, men der er intet i vejen i at bruge streng værdier i enums. Hans enum giver sikkert meget mening i de øvre abstraktions niveau (typisk i forretningslogik laget).
Avatar billede Syska Mester
21. december 2010 - 23:02 #26
Hvis det endelig var det ... så kan du jo stadig netop få ukorrekte værdier ind, da du selv siger den falder tilbage til en int, hvis string værdien ikke findes. ( Altså efter hvordan du laver din casting af string to enum )

Jeg ville bare være sikker på at han er klar over, at han som sådan intet vinder ved det, hvis han alligevel laver sin Enum om til string. Hvorfor så caste til din enum ... :-s

string->enum->string == "EnumStrinValue"

Det virker da sådan lidt mærkeligt, hvis jeg ellers har forstået det rigtigt.

mvh
Avatar billede d3crypt0 Nybegynder
21. december 2010 - 23:06 #27
Der må være noget fejlhåndtering, der tager sig af det. Alt andet vil være at stole blindt på, hvad man får tilbage.
Avatar billede CodingJoe Nybegynder
21. december 2010 - 23:24 #28
wow...der har været gang i den her selv efter spørgsmålet var lukket.

@d3crypto
Du har fuldstændig ret. Jeg har 5 faste streng værdier jeg opererer med, derfor er valget faldet på enum. De samme værdier findes i databasen, og de kan på ingen måder have en anden værdi end de 5. Er der en forkert værdi i databasen, er det en anden applikation, der har lagt noget invalid data ind.
Udover dette så har jeg faktisk fejlhåndtering rundt om, hvis en mapping skulle fejle. Så ingen problemer her.

@Buzzz tak for din bekymring, men jeg har gode erfaringer med enums, der holder streng værdier frem for integers, som du måske mere er vant til.
Avatar billede Syska Mester
21. december 2010 - 23:31 #29
Ja, men en gang skal også være den første gang det fejler.

Jeg ville stadig have en constraint på den column, så der aldrig kan komme invalid data i den ... men det er måske bare mig.

Hvis du alligevel sammenligner med en string, hvorfor så caste din string til en enum og tilbage igen ... den kan jeg stadig ikke helt gennemskue.

Din type sikkerhed forsvinder jo ...
Avatar billede d3crypt0 Nybegynder
21. december 2010 - 23:38 #30
Det er streng værdien af enum, der bliver sammenlignet med en værdi i 'where'... l.Category.ToString() == myCategory. Type sikkerheden findes ikke, da enum ikke supporteret i SQL endnu.

Bliver nødt til at smutte i seng nu godnat alle.
Avatar billede johny Nybegynder
22. december 2010 - 18:06 #31
Hmm, kunne alt det her ikke klares pænere vha. partielle klasser, eller er det kun en feature i LinqToEntities?
Avatar billede Syska Mester
22. december 2010 - 19:29 #32
nej, Linq2Sql er også partial classes.

mvh
Avatar billede janus_007 Nybegynder
22. december 2010 - 19:34 #33
Jeg er ikke helt enig i at autogenereret kode er evil, faktisk er det ret smart når koden er triviel. Jeg gider simpelthen ikke sidde og kode noget som andre allerede har påtaget sig ansvaret for virker :) Når det så er sagt, så afhænger det naturligvis meget af hvilken kode vi snakker om, men eks.vis Linq To... her synes jeg bare at tingene skal være så simple som muligt.

Jo.. partial kan også lave i Ling To Sql.

Derudover giver jeg buzzz ret, jeg synes også enum i det tilfælde her virker underligt forgjort og unødvendigt :) Jeg prøver altid at holde koden så simpel som mulig :)
Avatar billede Syska Mester
22. december 2010 - 19:43 #34
Auto genereret kode er smart ... i mange tilfælge :-) Bare ikke når man går ind og andre det ... og at skal huske at lave sin egne ændringer i det.

T4 templates bliver jo brugt mere og mere ... og ikke helt uden grund.

Som janus_007 er inde på, så bør man kunne stole på det, det er jo i mange tilfælde .NET selv som laver det autogenererede kode ... eller bør man jo betvivle alt kode. :-)

mvh
Avatar billede johny Nybegynder
22. december 2010 - 20:42 #35
Igen, hvorfor er det så ikke at man blot bruger partielle klasser til at løse den her?

namespace "namespace på entitetsklasserne"
{
public partial class MyObject
{
public Category CategoryEnum
{
get
{
return (Category)Enum.Parse(typeof(Category), this.Category);
}
set
{
this.Category = value.ToString();
}
}
}
}

Umiddelbart virker det da til at være den simpleste løsning uden nogen umiddelbare problemer?
Avatar billede Syska Mester
22. december 2010 - 23:10 #36
Ja ...

Men du må ikke sprøge mig om det ... det virker lidt mærkeligt at parse den ... hvis den ikke skal bruges, men jeg mener det samme som dig.

mvh
Avatar billede johny Nybegynder
23. december 2010 - 09:08 #37
Er vel for at være mere explicit i sin kode. Jeg selv kan også bedre lide at arbejde med enums end const string klasser. Men ja, er så måske også fordi jeg så ofte bruger flags, at enums er det naturlige valg for mig når muligheden byder sig. E.g. så snart jeg har 3 states, så laver jeg en privat enum.
Avatar billede bvli Praktikant
23. december 2010 - 13:44 #38
Jeg vil også lige blande mig for jeg har egentlig også svært ved at forstå hvad galt der er i at bruge en enum her. Det er da fuldt ud ligeså typesikkert at parse den fra en streng end fra en int. Ja faktisk er det meget bedre stil at parse den fra streng, da du vil få en exception hvis man prøver at smide en fejlagtig værdi i enum'en, når den kommer tilbage fra databasen.

Derudover er det altså også noget mere læseligt, i selve databasen at have navnet på værdien frem for et tilfældigt tal.

Fejlen ved enums er jo, at de ikke er typesikre.
Avatar billede d3crypt0 Nybegynder
23. december 2010 - 19:02 #39
Jeg kan se debatten har fortsat siden sidst. Jeg ser heller ingen problemer ved at bruge tekstuelle værdier som enums, da det netop låser værdier i afgrænsede logiske enheder. Jeg giver janus ret i at det kan være skidt at rette i autogenerede filer og microsoft er blevet bedre til at overholde deres egne navngivnings konventioner i deres autogenererede filer. Jeg er mest tilhænger af at skrive tingene selv, hvorfor jeg også foretrækker at bruge channelfactory fremfor proxy klasser. Det lille hack er et opråb for mig til microsoft, så de kan tage sig sammen til at åbne op for håndtering af enums mapping med strenge til deres implementation af linq to sql. At tilføje en partial klasse kan også være en farbar vej, men synes det er for omstændigt at øge kompleksiteten af koden på noget så banalt som enums.
Avatar billede janus_007 Nybegynder
23. december 2010 - 21:16 #40
En idé kunne måske være at bruge specification pattern eller måske en hybrid af det implementeret som extension.

Jeg tænker noget alá:

public static class Extensions
{
public static IQueryable<Foo> FilterUsingEnum(this IQueryable<Foo> foo, YourEnum value)

// write filter logic using your enum.. convert value to strings

  return foo.Where(x => x.Field = yourconvertedEnumToString().....)
}

nb: bær over med min opfindsomme navngivning ;-)
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester