11using System ;
22using System . Collections . Generic ;
33using System . Data ;
4+ using System . Globalization ;
45using System . Linq ;
56using System . Text . Json . Nodes ;
67using GeneXus . Data . NTier ;
@@ -10,19 +11,52 @@ namespace GeneXus.Data.Cosmos
1011{
1112 internal class CosmosDBHelper
1213 {
14+ internal const string ISO_DATE_FORMAT = "yyyy-MM-ddTHH:mm:ss:fffK" ;
1315 internal static PartitionKey ToPartitionKey ( object value )
1416 {
1517 if ( value is double )
1618 return new PartitionKey ( ( double ) value ) ;
1719 if ( value is bool )
1820 return new PartitionKey ( ( bool ) value ) ;
1921 if ( value is string )
20- return new PartitionKey ( ( string ) value ) ;
22+ return new PartitionKey ( ( string ) value ) ;
23+ if ( value is decimal )
24+ {
25+ decimal valueDecimal = ( decimal ) value ;
26+ try
27+ {
28+ double convertedDouble = ( double ) value ;
29+ decimal convertedDecimal = ( decimal ) convertedDouble ;
30+
31+ //Possible loss of precision when converting from decimal to double
32+
33+ if ( valueDecimal != convertedDecimal )
34+ throw new Exception ( "Loss of precision converting from decimal to double. Partitionkey should be double." ) ;
35+ else
36+ return new PartitionKey ( convertedDouble ) ;
37+ }
38+ catch
39+ {
40+ try
41+ {
42+ double convertedDouble = Convert . ToDouble ( value ) ;
43+ decimal convertedDecimal = Convert . ToDecimal ( convertedDouble ) ;
44+ if ( valueDecimal != convertedDecimal )
45+ throw new Exception ( "Loss of precision converting from decimal to double. Partitionkey should be double." ) ;
46+ else
47+ return new PartitionKey ( convertedDouble ) ;
48+ }
49+ catch
50+ {
51+ throw new Exception ( "Loss of precision converting from decimal to double. Partitionkey should be double." ) ;
52+ }
53+ }
54+ }
2155 else
2256 throw new Exception ( "Partitionkey can be double, bool or string." ) ;
2357 }
2458 internal static bool AddItemValue ( string parmName , string fromName , Dictionary < string , object > values , IDataParameterCollection parms , IEnumerable < VarValue > queryVars , ref JsonObject jsonObject )
25- {
59+ {
2660 if ( ! AddItemValue ( parmName , values , parms [ fromName ] as ServiceParameter , ref jsonObject ) )
2761 {
2862 VarValue varValue = queryVars . FirstOrDefault ( v => v . Name == $ ":{ fromName } ") ;
@@ -34,20 +68,36 @@ internal static bool AddItemValue(string parmName, string fromName, Dictionary<s
3468 jsonObject . Add ( keyvalue ) ;
3569 }
3670 else
37- jsonObject . Add ( parmName , JsonValue . Create ( varValue . Value ) ) ;
71+ if ( FormattedAsStringDateGXType ( varValue . Type ) )
72+ {
73+ DateTime dt = DateTime . SpecifyKind ( ( DateTime ) varValue . Value , DateTimeKind . Utc ) ;
74+ jsonObject . Add ( parmName , dt . ToString ( ISO_DATE_FORMAT ) ) ;
75+ }
76+ else
77+ jsonObject . Add ( parmName , JsonValue . Create ( varValue . Value ) ) ;
3878 values [ parmName ] = varValue . Value ;
3979 }
4080 return varValue != null ;
4181 }
4282 return true ;
4383 }
44- public static bool FormattedAsStringGXType ( GXType gXType )
84+
85+ internal static bool FormattedAsStringDateGXType ( GXType gXType )
86+ {
87+ return ( gXType == GXType . Date || gXType == GXType . DateTime || gXType == GXType . DateTime2 ) ;
88+ }
89+ internal static bool FormattedAsStringGXType ( GXType gXType )
4590 {
46- return ( gXType == GXType . Date || gXType == GXType . DateTime || gXType == GXType . DateTime2 || gXType == GXType . VarChar || gXType == GXType . DateAsChar || gXType == GXType . NVarChar || gXType == GXType . LongVarChar || gXType == GXType . NChar || gXType == GXType . Char || gXType == GXType . Text || gXType == GXType . NText ) ;
91+ return ( gXType == GXType . VarChar || gXType == GXType . DateAsChar || gXType == GXType . NVarChar || gXType == GXType . LongVarChar || gXType == GXType . NChar || gXType == GXType . Char || gXType == GXType . Text || gXType == GXType . NText ) ;
92+ }
93+
94+ internal static bool FormattedAsStringDateDbType ( DbType dbType )
95+ {
96+ return ( dbType == DbType . Date || dbType == DbType . DateTime || dbType == DbType . DateTime2 || dbType == DbType . DateTimeOffset || dbType == DbType . Time ) ;
4797 }
4898 internal static bool FormattedAsStringDbType ( DbType dbType )
4999 {
50- return ( dbType == DbType . String || dbType == DbType . Date || dbType == DbType . DateTime || dbType == DbType . DateTime2 || dbType == DbType . DateTimeOffset || dbType == DbType . StringFixedLength || dbType == DbType . AnsiString || dbType == DbType . AnsiStringFixedLength || dbType == DbType . Guid || dbType == DbType . Time ) ;
100+ return ( dbType == DbType . String || dbType == DbType . StringFixedLength || dbType == DbType . AnsiString || dbType == DbType . AnsiStringFixedLength || dbType == DbType . Guid ) ;
51101 }
52102 internal static string FormatExceptionMessage ( string statusCode , string message )
53103 {
@@ -65,7 +115,13 @@ internal static bool AddItemValue(string parmName, Dictionary<string, object> dy
65115 jsonObject . Add ( keyvalue ) ;
66116 }
67117 else
68- jsonObject . Add ( parmName , JsonValue . Create ( parm . Value ) ) ;
118+ if ( FormattedAsStringDateDbType ( parm . DbType ) )
119+ {
120+ DateTime dt = DateTime . SpecifyKind ( ( DateTime ) parm . Value , DateTimeKind . Utc ) ;
121+ jsonObject . Add ( parmName , dt . ToString ( ISO_DATE_FORMAT ) ) ;
122+ }
123+ else
124+ jsonObject . Add ( parmName , JsonValue . Create ( parm . Value ) ) ;
69125 dynParm [ parmName ] = parm . Value ;
70126 return true ;
71127 }
0 commit comments