@@ -8,6 +8,7 @@ namespace DataServices.Core;
88using System . Text ;
99using System . Text . Json ;
1010using System . Text . Json . Serialization ;
11+ using System . Globalization ;
1112using Common ;
1213using Hl7 . Fhir . Utility ;
1314using Microsoft . Azure . Functions . Worker . Http ;
@@ -281,9 +282,25 @@ private Expression<Func<TEntity, bool>> CreateGetByKeyExpression(string filter)
281282 {
282283 var entityParameter = Expression . Parameter ( typeof ( TEntity ) ) ;
283284 var entityKey = Expression . Property ( entityParameter , _keyInfo . Name ) ;
284- var filterConstant = Expression . Constant ( Convert . ChangeType ( filter , ReflectionUtilities . GetPropertyType ( typeof ( TEntity ) , _keyInfo . Name ) ) ) ;
285- var expr = Expression . Equal ( entityKey , filterConstant ) ;
285+ var keyType = ReflectionUtilities . GetPropertyType ( typeof ( TEntity ) , _keyInfo . Name ) ;
286286
287+ // Support nullable keys by comparing on the underlying type
288+ var underlyingType = Nullable . GetUnderlyingType ( keyType ) ?? keyType ;
289+
290+ // Convert the incoming filter string to the correct key type (e.g., Guid, int, etc.)
291+ object typedValue = ConvertKeyString ( filter , underlyingType ) ;
292+
293+ // Build a constant for the typed key value
294+ var filterConstant = Expression . Constant ( typedValue , underlyingType ) ;
295+
296+ // If the property is nullable, convert it to the underlying type for comparison
297+ Expression left = entityKey ;
298+ if ( underlyingType != keyType )
299+ {
300+ left = Expression . Convert ( entityKey , underlyingType ) ;
301+ }
302+
303+ var expr = Expression . Equal ( left , filterConstant ) ;
287304 return Expression . Lambda < Func < TEntity , bool > > ( expr , entityParameter ) ;
288305 }
289306
@@ -396,4 +413,29 @@ private static HttpResponseData CreateHttpResponse(HttpRequestData req, DataServ
396413 }
397414
398415
416+
417+ private static object ConvertKeyString ( string filter , Type targetType )
418+ {
419+ // Handle common non-ChangeType primitives
420+ if ( targetType == typeof ( Guid ) )
421+ {
422+ return Guid . Parse ( filter ) ;
423+ }
424+ if ( targetType . IsEnum )
425+ {
426+ return Enum . Parse ( targetType , filter , ignoreCase : true ) ;
427+ }
428+ if ( targetType == typeof ( DateTime ) )
429+ {
430+ return DateTime . Parse ( filter , CultureInfo . InvariantCulture , DateTimeStyles . RoundtripKind ) ;
431+ }
432+ if ( targetType == typeof ( string ) )
433+ {
434+ return filter ;
435+ }
436+
437+ // Fallback to Convert.ChangeType with invariant culture
438+ return Convert . ChangeType ( filter , targetType , CultureInfo . InvariantCulture ) ;
439+ }
440+
399441}
0 commit comments