parallax background image

Entity Framework: Hoofdlettergevoeligheid in SQL

Gepubliceerd op 30 december 2021 Leestijd : 3 minuten

Entity Framework is een mapper waarmee je objecten in je code kunt mappen met je database. Dit is vaak MS-SQL, maar kan ook een andere database zijn, zoals MySql of SqLite. Entity Framework zorgt ervoor dat je je bezig kunt houden met je applicatie, terwijl de database-koppeling geregeld wordt. Maar het blijft belangrijk om te beseffen welke databaseserver gebruikt wordt, omdat er soms database-specifieke regels kunnen gelden.

Een voorbeeld:

Er is een tabel Pages bestaande PageId, Id en Name:

foutmelding-dictionary.png.png

Via Entity Framework wil ik nu een aantal pagina’s ophalen op basis van hun naam:

Dictionary<string, string> dict = new Dictionary<string, string>();

dict.Add("c4586f8d-c347-43e4-983b-c7e4788abc57", "x");
dict.Add("1CDA085F-1539-47D0-B54B-2AF7134C44DB", "y");
dict.Add("7c8c0c6b-89dc-4f4f-b61c-5a0613e6be19", "z");

var keys = dict.Keys;
var pagesContains = context.Pages.Where(x => keys.Contains(x.Name)).ToList();

Deze drie staan in de database en krijg ik inderdaad terug. Ik maak gebruik van een Dictionary, omdat ik iets wil doen met de waardes 'x','y' en 'z', voor de betreffende pagina’s, bijvoorbeeld de Id aanpassen.

Ik loop door de gevonden pagina’s, om die bewerking uit te voeren, en krijg een foutmelding, omdat een bepaald item niet is gevonden:

resultaat-afbeeldingen.png

Dat is natuurlijk opmerkelijk, want zojuist heb ik ze wél kunnen ophalen uit de database op basis van de Name. Wat is hier aan de hand? In dit geval maakt Entity Framework een query die wordt uitgevoerd op de SQL-server. De database, in dit geval, en de query is echter case-insensitive, er wordt niet gelet op een verschil in kleine letters of hoofdletters.

De key van een Dictionary in C# daarentegen is wél hoofdlettergevoelig en vindt een bepaald object in de collectie niet.

Hoe dit op te lossen?

Collation toepassen op je query

Je kan dit oplossen door in he query COLLATE te gebruiken. Hiermee geef je aan dat de query gebruik moet maken van andere regels voor karakters.

select  * from Pages where Name = '86B2D64A-83BE-4D21-A246-C32DE5165B85'; 
select  * from Pages where Name = lower('86B2D64A-83BE-4D21-A246-C32DE5165B85') ; 

select  * from Pages where Name = '86B2D64A-83BE-4D21-A246-C32DE5165B85' COLLATE Latin1_General_CS_AS ; 
select  * from Pages where Name = lower('86B2D64A-83BE-4D21-A246-C32DE5165B85') COLLATE Latin1_General_CS_AS ; 

 

Dit houdt echter in dat je wel gebruik moet maken van een custom query in je C#-code: Entity Framework zelf biedt de mogelijkheid niet om de collation aan te passen.

ToLower of ToUpper gebruiken

Een tweede oplossing is om in C# de keys altijd om te zetten naar kleine letters of hoofdletters.

                Dictionary<string, string> dict = new Dictionary<string, string>();
                dict.Add("c4586f8d-c347-43e4-983b-c7e4788abc57".ToLower(), "x");
                dict.Add("1CDA085F-1539-47D0-B54B-2AF7134C44DB".ToLower(), "y");
                dict.Add("7c8c0c6b-89dc-4f4f-b61c-5a0613e6be19".ToLower(), "z");

                var keys = dict.Keys;
                var pagesContains = context.Pages.Where(x => keys.Contains(x.Name)).ToList();

                // pagesContains.Count == 3
                foreach (var page in pagesContains)
                {
                    var dictEntry = dict[page.Name.ToLower()];
                } 

Kortom, hoewel Entity Framework zoveel mogelijk werk van je overneemt, is het raadzaam om te weten welke techniek erachter hangt en welke eigenaardigheden die techniek met zich meebrengt.

Onze klanten