diff --git a/dotnet/DotNetStandardClasses.sln b/dotnet/DotNetStandardClasses.sln
index 94c5499b3..212c0e507 100644
--- a/dotnet/DotNetStandardClasses.sln
+++ b/dotnet/DotNetStandardClasses.sln
@@ -69,9 +69,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GXGoogleCloud", "src\dotnet
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "dynservice", "dynservice", "{A14C2C2C-ACE3-4712-A527-E4E5F02729FA}"
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DynService.Core", "src\dotnetframework\DynService.Core\DynService.Core.csproj", "{B0DEB9ED-9E0A-42E3-BBE1-9F70DD78DC93}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DynService.Core", "src\dotnetcommon\DynService.Core\DynService.Core.csproj", "{B0DEB9ED-9E0A-42E3-BBE1-9F70DD78DC93}"
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DynService.DynamoDB", "src\dotnetframework\DynService.Dynamo\DynService.DynamoDB.csproj", "{4DC1C813-E7C1-442E-B7D6-C9B932A55759}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DynService.DynamoDB", "src\dotnetcommon\DynService.Dynamo\DynService.DynamoDB.csproj", "{4DC1C813-E7C1-442E-B7D6-C9B932A55759}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DynService.Fabric", "src\dotnetframework\DynServiceFabric\DynService.Fabric.csproj", "{42D048EC-29C5-4553-B301-A6A5A76A7FB8}"
EndProject
@@ -119,8 +119,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DotNetUnitTest", "test\DotN
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "dynservice", "dynservice", "{79C9ECC6-2935-4C43-BF32-94698547F584}"
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DynService.Core", "src\dotnetcore\DynService\Core\DynService.Core.csproj", "{E2FB8843-503A-4A22-923E-B12510233127}"
-EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DynServiceOData", "src\dotnetcore\DynService\OData\DynServiceOData.csproj", "{2238FCB1-3A83-46C2-873E-82DA4266069D}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "azurefunctionhandlers", "azurefunctionhandlers", "{BD804A75-9F3F-416C-BF6B-D3DF6C4A8DC0}"
@@ -186,6 +184,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
..\.editorconfig = ..\.editorconfig
EndProjectSection
EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "dynservice", "dynservice", "{C264F34E-2CE0-4DCA-B22D-4155821BE611}"
+EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GxXsl", "src\dotnetcore\GxXsl\GxXsl.csproj", "{30E7E437-F9B0-42B8-9144-A8E8F972B462}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "mocking", "mocking", "{5045873B-E7CF-4317-94C1-0EF8623D23FA}"
@@ -394,10 +394,6 @@ Global
{251CCD53-21B3-4EBE-8627-49885C4E98B9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{251CCD53-21B3-4EBE-8627-49885C4E98B9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{251CCD53-21B3-4EBE-8627-49885C4E98B9}.Release|Any CPU.Build.0 = Release|Any CPU
- {E2FB8843-503A-4A22-923E-B12510233127}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {E2FB8843-503A-4A22-923E-B12510233127}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {E2FB8843-503A-4A22-923E-B12510233127}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {E2FB8843-503A-4A22-923E-B12510233127}.Release|Any CPU.Build.0 = Release|Any CPU
{2238FCB1-3A83-46C2-873E-82DA4266069D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2238FCB1-3A83-46C2-873E-82DA4266069D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2238FCB1-3A83-46C2-873E-82DA4266069D}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -533,8 +529,8 @@ Global
{F6372249-AF37-4455-B572-5BDF8DE2ACC8} = {F82842DA-F15E-49C5-993E-4C269818FF1F}
{E9072D95-D116-4D4B-B981-46146BCDE052} = {F82842DA-F15E-49C5-993E-4C269818FF1F}
{A14C2C2C-ACE3-4712-A527-E4E5F02729FA} = {F900A4AD-7249-41B4-B918-CB9E8C73747C}
- {B0DEB9ED-9E0A-42E3-BBE1-9F70DD78DC93} = {A14C2C2C-ACE3-4712-A527-E4E5F02729FA}
- {4DC1C813-E7C1-442E-B7D6-C9B932A55759} = {A14C2C2C-ACE3-4712-A527-E4E5F02729FA}
+ {B0DEB9ED-9E0A-42E3-BBE1-9F70DD78DC93} = {C264F34E-2CE0-4DCA-B22D-4155821BE611}
+ {4DC1C813-E7C1-442E-B7D6-C9B932A55759} = {C264F34E-2CE0-4DCA-B22D-4155821BE611}
{42D048EC-29C5-4553-B301-A6A5A76A7FB8} = {A14C2C2C-ACE3-4712-A527-E4E5F02729FA}
{9C521E63-7B6F-4AD3-ACB5-132175D9413A} = {A14C2C2C-ACE3-4712-A527-E4E5F02729FA}
{277490D7-8834-4722-9084-E894F804C66A} = {2261B65E-3757-4E5B-9DCD-EAE8D1E236A3}
@@ -557,7 +553,6 @@ Global
{55297803-2DE8-48C4-AB65-9D19E77614E1} = {1D6F1776-FF4B-46C2-9B3D-BC46CCF049DC}
{251CCD53-21B3-4EBE-8627-49885C4E98B9} = {1D6F1776-FF4B-46C2-9B3D-BC46CCF049DC}
{79C9ECC6-2935-4C43-BF32-94698547F584} = {2261B65E-3757-4E5B-9DCD-EAE8D1E236A3}
- {E2FB8843-503A-4A22-923E-B12510233127} = {79C9ECC6-2935-4C43-BF32-94698547F584}
{2238FCB1-3A83-46C2-873E-82DA4266069D} = {79C9ECC6-2935-4C43-BF32-94698547F584}
{BD804A75-9F3F-416C-BF6B-D3DF6C4A8DC0} = {C6AFB6A3-FF0B-4970-B1F1-10BCD3D932B2}
{41E1D031-799F-484F-85DE-7A30AF1A6FBA} = {BD804A75-9F3F-416C-BF6B-D3DF6C4A8DC0}
@@ -587,6 +582,7 @@ Global
{911BC7CC-4A07-408F-BA20-8BAB5355BE84} = {C8590651-46B6-4681-A6A0-0850B5A9A697}
{B59F76D8-FDB2-4F51-89DB-F15E9BDFF1DC} = {420E8A4A-11D9-42E9-BFB7-4325EA7330B8}
{D97E17A4-C945-4BF3-957E-F73142C4C6D0} = {947E032A-C385-4586-96E3-FC7D2767F082}
+ {C264F34E-2CE0-4DCA-B22D-4155821BE611} = {F1E13DF4-9F50-41A2-9DC3-04B673B21032}
{30E7E437-F9B0-42B8-9144-A8E8F972B462} = {2261B65E-3757-4E5B-9DCD-EAE8D1E236A3}
{5045873B-E7CF-4317-94C1-0EF8623D23FA} = {C6AFB6A3-FF0B-4970-B1F1-10BCD3D932B2}
{8E5A25F9-2D64-4742-8227-2A3C5816AFEC} = {5045873B-E7CF-4317-94C1-0EF8623D23FA}
diff --git a/dotnet/src/dotnetcommon/DynService.Core/DynService.Core.csproj b/dotnet/src/dotnetcommon/DynService.Core/DynService.Core.csproj
new file mode 100644
index 000000000..6d8118577
--- /dev/null
+++ b/dotnet/src/dotnetcommon/DynService.Core/DynService.Core.csproj
@@ -0,0 +1,21 @@
+
+
+ net462;net6.0
+ GeneXus.Data.NTier
+ GeneXus.Data.DynService.Core
+ CA1812
+ Dynservice
+ GeneXus.DynService.Core
+
+
+
+ NETCORE
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/dotnet/src/dotnetframework/DynService.Core/DynServiceCommon.cs b/dotnet/src/dotnetcommon/DynService.Core/DynServiceCommon.cs
similarity index 83%
rename from dotnet/src/dotnetframework/DynService.Core/DynServiceCommon.cs
rename to dotnet/src/dotnetcommon/DynService.Core/DynServiceCommon.cs
index 77cf83643..695113439 100644
--- a/dotnet/src/dotnetframework/DynService.Core/DynServiceCommon.cs
+++ b/dotnet/src/dotnetcommon/DynService.Core/DynServiceCommon.cs
@@ -16,21 +16,20 @@ namespace GeneXus.Data.NTier
{
public class Query
{
- private object mDataStoreHelper;
-
public string TableName { get; set; } = String.Empty;
- public string[] Projection { get; set; } = Array.Empty();
- public string[] OrderBys { get; set; } = Array.Empty();
- public string[] Filters { get; set; } = Array.Empty();
- public string[] AssignAtts { get; set; } = Array.Empty();
- public IODataMap2[] SelectList { get; set; } = Array.Empty();
- public VarValue[] Vars { get; set; } = Array.Empty();
+ public IEnumerable Projection { get; set; } = Array.Empty();
+ public IEnumerable OrderBys { get; set; } = Array.Empty();
+ public IEnumerable Filters { get; set; } = Array.Empty();
+ private List> mAssignAtts;
+ public IEnumerable> AssignAtts { get { return mAssignAtts ?? Array.Empty>() as IEnumerable>; } }
+ public IEnumerable SelectList { get; set; } = Array.Empty();
+
+ private List mVarValues;
+ public IEnumerable Vars { get { return (mVarValues ?? Array.Empty() as IEnumerable); } }
public CursorType CursorType { get; set; } = CursorType.Select;
- public Query(object dataStoreHelper)
- {
- mDataStoreHelper = dataStoreHelper;
- }
+ public Query(object dataStoreHelper) { }
+
public Query For(string v)
{
TableName = v;
@@ -54,9 +53,10 @@ public Query Filter(string[] filters)
return this;
}
- public Query Set(string[] assignAtts)
+ public Query Set(string name, string value)
{
- AssignAtts = assignAtts;
+ mAssignAtts = mAssignAtts ?? new List>();
+ mAssignAtts.Add(new KeyValuePair(name, value));
return this;
}
@@ -66,11 +66,6 @@ public Query SetMaps(IODataMap2[] iODataMap)
return this;
}
- public Query SetVars(VarValue[] vars)
- {
- Vars = vars;
- return this;
- }
public Query SetType(CursorType cType)
{
@@ -78,6 +73,12 @@ public Query SetType(CursorType cType)
return this;
}
+ public Query AddConst(GXType gxType, object parm)
+ {
+ mVarValues = mVarValues ?? new List();
+ mVarValues.Add(new VarValue($":const{ mVarValues.Count + 1 }", gxType, parm));
+ return this;
+ }
}
public class VarValue
@@ -89,24 +90,18 @@ public class VarValue
public VarValue(string name, GXType type, object value)
{
Name = name;
+ Type = type;
Value = value;
}
}
- public class QueryExpression
- {
- public string For { get; set; }
- internal string[] Select { get; set; }
- }
-
-
public interface IODataMap2
{
object GetValue(IOServiceContext serviceContext, RecordEntryRow currentEntry);
string GetName(IOServiceContext serviceContext);
- void SetValue(IOServiceContext serviceContext, RecordEntryRow currentEntry, object value);
+ void SetValue(RecordEntryRow currentEntry, object value);
}
@@ -129,7 +124,7 @@ public virtual object GetValue(IOServiceContext context, RecordEntryRow currentE
throw new NotImplementedException();
}
- public virtual void SetValue(IOServiceContext context, RecordEntryRow currentEntry, object value)
+ public virtual void SetValue(RecordEntryRow currentEntry, object value)
{
throw new NotImplementedException();
}
@@ -157,7 +152,15 @@ public interface IODataMap
void SetValue(IDictionary currentEntry, object value);
}
- public abstract class DynServiceDataStoreHelper : DataStoreHelperBase
+ public abstract class DynServiceDataStoreHelperBase : DataStoreHelperBase
+ {
+ public static object InvalidQuery(string msg)
+ {
+ throw new ServiceException(msg);
+ }
+ }
+
+ public abstract class DynServiceDataStoreHelper : DynServiceDataStoreHelperBase
{
public abstract Guid GetParmGuid(IDataParameterCollection parms, string parm);
public abstract string GetParmStr(IDataParameterCollection parms, string parm);
diff --git a/dotnet/src/dotnetcommon/DynService.Core/GlobalSuppressions.cs b/dotnet/src/dotnetcommon/DynService.Core/GlobalSuppressions.cs
new file mode 100644
index 000000000..3dc76b4ab
--- /dev/null
+++ b/dotnet/src/dotnetcommon/DynService.Core/GlobalSuppressions.cs
@@ -0,0 +1,5 @@
+// This file is used by Code Analysis to maintain SuppressMessage
+// attributes that are applied to this project.
+// Project-level suppressions either have no target or are given
+// a specific target and scoped to a namespace, type, member, etc.
+
diff --git a/dotnet/src/dotnetframework/DynService.Core/Properties/AssemblyInfo.cs b/dotnet/src/dotnetcommon/DynService.Core/Properties/AssemblyInfo.cs
similarity index 100%
rename from dotnet/src/dotnetframework/DynService.Core/Properties/AssemblyInfo.cs
rename to dotnet/src/dotnetcommon/DynService.Core/Properties/AssemblyInfo.cs
diff --git a/dotnet/src/dotnetcommon/DynService.Dynamo/DynService.DynamoDB.csproj b/dotnet/src/dotnetcommon/DynService.Dynamo/DynService.DynamoDB.csproj
new file mode 100644
index 000000000..cafcef4b2
--- /dev/null
+++ b/dotnet/src/dotnetcommon/DynService.Dynamo/DynService.DynamoDB.csproj
@@ -0,0 +1,31 @@
+
+
+ net462;net6.0
+ GeneXus.Data.NTier
+ GeneXus.Data.DynService.DynamoDB
+ false
+ DynamoDB
+ GeneXus.DynService.DynamoDB
+
+
+
+ NETCORE
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
\ No newline at end of file
diff --git a/dotnet/src/dotnetcommon/DynService.Dynamo/DynamoDBConnection.cs b/dotnet/src/dotnetcommon/DynService.Dynamo/DynamoDBConnection.cs
new file mode 100644
index 000000000..f3b2acf9d
--- /dev/null
+++ b/dotnet/src/dotnetcommon/DynService.Dynamo/DynamoDBConnection.cs
@@ -0,0 +1,340 @@
+using Amazon;
+using Amazon.DynamoDBv2;
+using Amazon.DynamoDBv2.Model;
+using Amazon.Runtime;
+using GeneXus.Data.Dynamo;
+using GeneXus.Data.NTier.DynamoDB;
+using System;
+using System.Collections.Generic;
+using System.Data;
+using System.Data.Common;
+using System.Text.RegularExpressions;
+using System.Linq;
+using System.Net;
+using System.Text;
+using GeneXus.Cache;
+
+namespace GeneXus.Data.NTier
+{
+
+ public class DynamoDBService: GxService
+ {
+ public DynamoDBService(string id, string providerId): base(id, providerId, typeof(DynamoDBConnection))
+ {
+
+ }
+
+ public override IDataReader GetCacheDataReader(CacheItem item, bool computeSize, string keyCache)
+ {
+ return new GxDynamoDBCacheDataReader(item, computeSize, keyCache);
+ }
+ }
+
+ public class DynamoDBConnection : ServiceConnection
+ {
+ private readonly string CLIENT_ID = "User Id";
+ private readonly string CLIENT_SECRET = "password";
+ private readonly string REGION = "region";
+ private readonly string LOCAL_URL = "LocalUrl";
+ private readonly char[] SHARP_CHARS = new char[] { '#' };
+ private AmazonDynamoDBClient mDynamoDB;
+ private AmazonDynamoDBConfig mConfig;
+ private AWSCredentials mCredentials;
+ private RegionEndpoint mRegion = RegionEndpoint.USEast1;
+
+ private void InitializeDBConnection()
+ {
+ DbConnectionStringBuilder builder = new DbConnectionStringBuilder(false);
+ builder.ConnectionString = this.ConnectionString;
+ mConfig = new AmazonDynamoDBConfig();
+ string mLocalUrl = null;
+ if (builder.TryGetValue(LOCAL_URL, out object localUrl))
+ {
+ mLocalUrl = localUrl.ToString();
+ }
+ if (builder.TryGetValue(CLIENT_ID, out object clientId) && builder.TryGetValue(CLIENT_SECRET, out object clientSecret))
+ {
+ mCredentials = new BasicAWSCredentials(clientId.ToString(), clientSecret.ToString());
+ }
+ if (builder.TryGetValue(REGION, out object region))
+ {
+ mRegion = RegionEndpoint.GetBySystemName(region.ToString());
+ }
+
+ if (localUrl != null)
+ {
+ mConfig.ServiceURL = mLocalUrl;
+ if (region != null)
+ mConfig.AuthenticationRegion = region as string;
+ }
+ else
+ mConfig.RegionEndpoint = mRegion;
+ }
+
+ private void Initialize()
+ {
+ InitializeDBConnection();
+ State = ConnectionState.Executing;
+
+ mDynamoDB = new AmazonDynamoDBClient(mCredentials, mConfig);
+ }
+
+ private const string FILTER_PATTERN = @"\((.*) = :(.*)\)";
+
+ public override int ExecuteNonQuery(ServiceCursorDef cursorDef, IDataParameterCollection parms, CommandBehavior behavior)
+ {
+ Initialize();
+ DynamoQuery query = cursorDef.Query as DynamoQuery;
+ bool isInsert = query.CursorType == ServiceCursorDef.CursorType.Insert;
+
+ Dictionary values = new Dictionary();
+ Dictionary expressionAttributeNames = null;
+ HashSet mappedNames = null;
+ string keyItemForUpd = query.PartitionKey;
+ if (keyItemForUpd != null && keyItemForUpd.StartsWith("#"))
+ {
+ expressionAttributeNames = new Dictionary();
+ mappedNames = mappedNames ?? new HashSet();
+ string keyName = keyItemForUpd.Substring(1);
+ expressionAttributeNames.Add(keyItemForUpd, keyName);
+ mappedNames.Add(keyName);
+ }
+ foreach (KeyValuePair asg in query.AssignAtts)
+ {
+ string name = asg.Key;
+ if (name.StartsWith("#"))
+ {
+ if (!isInsert)
+ {
+ expressionAttributeNames = new Dictionary();
+ mappedNames = mappedNames ?? new HashSet();
+ string keyName = name.Substring(1);
+ expressionAttributeNames.Add(name, keyName);
+ mappedNames.Add(keyName);
+ }
+ name = name.Substring(1);
+ }
+ string parmName = asg.Value.Substring(1);
+ DynamoDBHelper.AddAttributeValue(isInsert ? name : $":{ name }", parmName, values, parms, query.Vars);
+ }
+
+ Dictionary keyCondition = new Dictionary();
+
+ foreach (string keyFilter in query.KeyFilters.Concat(query.Filters))
+ {
+ Match match = Regex.Match(keyFilter, FILTER_PATTERN);
+ if (match.Groups.Count > 1)
+ {
+ string varName = match.Groups[2].Value;
+ string name = match.Groups[1].Value.TrimStart(SHARP_CHARS);
+ VarValue varValue = query.Vars.FirstOrDefault(v => v.Name == $":{varName}");
+ if (varValue != null)
+ keyCondition[name] = DynamoDBHelper.ToAttributeValue(varValue);
+ else
+ {
+ if (parms[varName] is ServiceParameter serviceParm)
+ keyCondition[name] = DynamoDBHelper.ToAttributeValue(serviceParm.DbType, serviceParm.Value);
+ }
+ }
+ }
+ AmazonDynamoDBRequest request;
+ AmazonWebServiceResponse response = null;
+
+ switch (query.CursorType)
+ {
+ case ServiceCursorDef.CursorType.Select:
+ throw new NotImplementedException();
+
+ case ServiceCursorDef.CursorType.Delete:
+ request = new DeleteItemRequest()
+ {
+ TableName = query.TableName,
+ Key = keyCondition,
+ ConditionExpression = $"attribute_exists({ keyItemForUpd })",
+ ExpressionAttributeNames = expressionAttributeNames
+ };
+ try
+ {
+#if NETCORE
+ response = DynamoDBHelper.RunSync(() => mDynamoDB.DeleteItemAsync((DeleteItemRequest)request));
+#else
+ response = mDynamoDB.DeleteItem((DeleteItemRequest)request);
+#endif
+ }
+ catch (ConditionalCheckFailedException recordNotFound)
+ {
+ throw new ServiceException(ServiceError.RecordNotFound, recordNotFound);
+ }
+ break;
+ case ServiceCursorDef.CursorType.Insert:
+ request = new PutItemRequest
+ {
+ TableName = query.TableName,
+ Item = values,
+ ConditionExpression = $"attribute_not_exists({ keyItemForUpd })",
+ ExpressionAttributeNames = expressionAttributeNames
+ };
+ try
+ {
+#if NETCORE
+ response = DynamoDBHelper.RunSync(() => mDynamoDB.PutItemAsync((PutItemRequest)request));
+#else
+ response = mDynamoDB.PutItem((PutItemRequest)request);
+#endif
+ }
+ catch (ConditionalCheckFailedException recordAlreadyExists)
+ {
+ throw new ServiceException(ServiceError.RecordAlreadyExists, recordAlreadyExists);
+ }
+ break;
+ case ServiceCursorDef.CursorType.Update:
+ request = new UpdateItemRequest
+ {
+ TableName = query.TableName,
+ Key = keyCondition,
+ UpdateExpression = ToAttributeUpdates(keyCondition, values, mappedNames),
+ ConditionExpression = $"attribute_exists({ keyItemForUpd })",
+ ExpressionAttributeValues = values,
+ ExpressionAttributeNames = expressionAttributeNames
+ };
+ try
+ {
+#if NETCORE
+ response = DynamoDBHelper.RunSync(() => mDynamoDB.UpdateItemAsync((UpdateItemRequest)request));
+#else
+ response = mDynamoDB.UpdateItem((UpdateItemRequest)request);
+#endif
+ }
+ catch (ConditionalCheckFailedException recordNotFound)
+ {
+ throw new ServiceException(ServiceError.RecordNotFound, recordNotFound);
+ }
+ break;
+ }
+
+ return response?.HttpStatusCode == HttpStatusCode.OK ? 1 : 0;
+ }
+
+ private string ToAttributeUpdates(Dictionary keyConditions, Dictionary values, HashSet mappedNames)
+ {
+ StringBuilder updateExpression = new StringBuilder();
+ foreach (var item in values)
+ {
+ string keyName = item.Key.Substring(1);
+ if (!keyConditions.ContainsKey(keyName) && !keyName.StartsWith("AV", StringComparison.InvariantCulture))
+ {
+ if (mappedNames?.Contains(keyName) == true)
+ keyName = $"#{keyName}";
+ updateExpression.Append(updateExpression.Length == 0 ? "SET " : ", ");
+ updateExpression.Append($"{ keyName } = { item.Key }");
+ }
+ }
+ return updateExpression.ToString();
+ }
+
+ public override IDataReader ExecuteReader(ServiceCursorDef cursorDef, IDataParameterCollection parms, CommandBehavior behavior)
+ {
+
+ Initialize();
+ DynamoQuery query = cursorDef.Query as DynamoQuery;
+
+ try
+ {
+ CreateDynamoQuery(query, GetQueryValues(query, parms), out DynamoDBDataReader dataReader, out AmazonDynamoDBRequest req);
+ RequestWrapper reqWrapper = new RequestWrapper(mDynamoDB, req);
+ dataReader = new DynamoDBDataReader(cursorDef, reqWrapper);
+ return dataReader;
+ }
+ catch (AmazonDynamoDBException e)
+ {
+ if (e.ErrorCode == DynamoDBErrors.ValidationException &&
+ e.Message.Contains(DynamoDBErrors.ValidationExceptionMessageKey))
+ throw new ServiceException(ServiceError.RecordNotFound); // Handles special case where a string key attribute is filtered with an empty value which is not supported on DynamoDB but should yield a not record found in GX
+ throw e;
+ }
+ catch (AmazonServiceException e) { throw e; }
+ catch (Exception e) { throw e; }
+ }
+
+ private Dictionary GetQueryValues(DynamoQuery query, IDataParameterCollection parms)
+ {
+ Dictionary values = new Dictionary();
+ foreach (object parm in parms)
+ DynamoDBHelper.GXToDynamoQueryParameter(values, parm as ServiceParameter);
+ foreach (VarValue item in query.Vars)
+ values.Add(item.Name, DynamoDBHelper.ToAttributeValue(item));
+ return values;
+ }
+
+ private static void CreateDynamoQuery(DynamoQuery query, Dictionary values, out DynamoDBDataReader dataReader, out AmazonDynamoDBRequest req)
+ {
+ dataReader = null;
+ req = null;
+ Dictionary expressionAttributeNames = null;
+ foreach (string mappedName in query.SelectList.Where(selItem => (selItem as DynamoDBMap)?.NeedsAttributeMap == true).Select(selItem => selItem.GetName(NewServiceContext())))
+ {
+ expressionAttributeNames = expressionAttributeNames ?? new Dictionary();
+ string key = $"#{ mappedName }";
+ string value = mappedName;
+ expressionAttributeNames.Add(key, value);
+ }
+
+ bool issueScan = query is DynamoScan;
+ if (!issueScan)
+ { // Check whether a query has to be demoted to scan due to empty parameters
+ foreach (string keyFilter in query.KeyFilters)
+ {
+ Match match = Regex.Match(keyFilter, @".*(:.*)\).*");
+ if (match.Groups.Count > 0)
+ {
+ string varName = match.Groups[1].Value;
+ if(values.TryGetValue(varName, out AttributeValue value) && value.S?.Length == 0)
+ {
+ issueScan = true;
+ break;
+ }
+ }
+ }
+ }
+
+ if (issueScan)
+ {
+ ScanRequest scanReq;
+ IEnumerable allFilters = query.KeyFilters.Concat(query.Filters);
+ req = scanReq = new ScanRequest
+ {
+ TableName = query.TableName,
+ ProjectionExpression = String.Join(",", query.Projection),
+ FilterExpression = allFilters.Any() ? String.Join(" AND ", allFilters) : null,
+ ExpressionAttributeValues = values,
+ };
+ if (expressionAttributeNames != null)
+ scanReq.ExpressionAttributeNames = expressionAttributeNames;
+ }
+ else
+ {
+ QueryRequest queryReq;
+ req = queryReq = new QueryRequest
+ {
+ TableName = query.TableName,
+ KeyConditionExpression = String.Join(" AND ", query.KeyFilters),
+ FilterExpression = query.Filters.Any() ? String.Join(" AND ", query.Filters) : null,
+ ExpressionAttributeValues = values,
+ ProjectionExpression = String.Join(",", query.Projection),
+ IndexName = query.Index,
+ ScanIndexForward = query.ScanIndexForward,
+ };
+ if (expressionAttributeNames != null)
+ queryReq.ExpressionAttributeNames = expressionAttributeNames;
+ }
+ }
+ internal static IOServiceContext NewServiceContext() => null;
+
+ }
+
+ public class DynamoDBErrors
+ {
+ public const string ValidationException = "ValidationException";
+ public const string ValidationExceptionMessageKey = "The AttributeValue for a key attribute cannot contain an empty string value.";
+ }
+}
diff --git a/dotnet/src/dotnetframework/DynService.Dynamo/DynamoDBDataReader.cs b/dotnet/src/dotnetcommon/DynService.Dynamo/DynamoDBDataReader.cs
similarity index 62%
rename from dotnet/src/dotnetframework/DynService.Dynamo/DynamoDBDataReader.cs
rename to dotnet/src/dotnetcommon/DynService.Dynamo/DynamoDBDataReader.cs
index 641fea832..cb659a2e4 100644
--- a/dotnet/src/dotnetframework/DynService.Dynamo/DynamoDBDataReader.cs
+++ b/dotnet/src/dotnetcommon/DynService.Dynamo/DynamoDBDataReader.cs
@@ -1,24 +1,23 @@
using System;
using System.Collections.Generic;
using System.Data;
+using System.Globalization;
+using System.IO;
using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
using Amazon.DynamoDBv2.Model;
using GeneXus.Cache;
-using GeneXus.Data.Dynamo;
using GeneXus.Data.NTier;
using GeneXus.Data.NTier.DynamoDB;
-using log4net;
namespace GeneXus.Data.Dynamo
{
public class DynamoDBDataReader : IDataReader
{
- private RequestWrapper mRequest;
+ private readonly RequestWrapper mRequest;
private ResponseWrapper mResponse;
- private int mCurrentPosition = -1;
- private IODataMap2[] selectList;
+ private int mCurrentPosition;
+ private readonly IODataMap2[] selectList;
+ private DynamoDBRecordEntry currentEntry;
private int ItemCount
{
@@ -36,24 +35,26 @@ private List> Items
}
}
- public DynamoDBDataReader(ServiceCursorDef cursorDef, RequestWrapper request, IDataParameterCollection parameters)
+ private void CheckCurrentPosition()
+ {
+ if (currentEntry == null)
+ throw new ServiceException(ServiceError.RecordNotFound);
+ }
+
+ public DynamoDBDataReader(ServiceCursorDef cursorDef, RequestWrapper request)
{
Query query = cursorDef.Query as Query;
- selectList = query.SelectList;
+ selectList = query.SelectList.ToArray();
mRequest = request;
mResponse = mRequest.Read();
+ mCurrentPosition = -1;
}
public object this[string name]
{
get
{
- if (mCurrentPosition >= 0 && mCurrentPosition < ItemCount)
- {
- return Items[mCurrentPosition][name].S;
- }
- throw new ArgumentOutOfRangeException(nameof(name));
-
+ throw new NotImplementedException();
}
}
@@ -61,16 +62,7 @@ public object this[int i]
{
get
{
- if (mCurrentPosition >= 0 && mCurrentPosition < ItemCount)
- {
- int j = 0;
- foreach (var col in Items[mCurrentPosition])
- {
- if (j == i)
- return col.Value.S;
- }
- }
- throw new ArgumentOutOfRangeException(nameof(i));
+ throw new NotImplementedException();
}
}
@@ -120,12 +112,13 @@ public void Dispose()
public long getLong(int i)
{
- return Convert.ToInt64(GetAttValue(i).N);
+ return Convert.ToInt64(GetAttValueN(i));
}
public bool GetBoolean(int i)
{
- return GetAttValue(i).BOOL;
+ AttributeValue value = GetAttValue(i);
+ return value.IsBOOLSet && value.BOOL;
}
public byte GetByte(int i)
@@ -135,7 +128,11 @@ public byte GetByte(int i)
public long GetBytes(int i, long fieldOffset, byte[] buffer, int bufferoffset, int length)
{
- throw new NotImplementedException();
+ MemoryStream ms = GetAttValue(i).B;
+ if (ms == null)
+ return 0;
+ ms.Seek(fieldOffset, SeekOrigin.Begin);
+ return ms.Read(buffer, bufferoffset, length);
}
public char GetChar(int i)
@@ -145,8 +142,7 @@ public char GetChar(int i)
public long GetChars(int i, long fieldoffset, char[] buffer, int bufferoffset, int length)
{
- buffer = GetAttValue(i).S.ToCharArray();
- return buffer.Length;
+ throw new NotImplementedException();
}
public IDataReader GetData(int i)
@@ -161,29 +157,28 @@ public string GetDataTypeName(int i)
public DateTime GetDateTime(int i)
{
- DateTime dt = new DateTime();
- DateTime.TryParse(GetAttValue(i).S, out dt);
+ DateTime.TryParse(GetAttValue(i).S, null, DateTimeStyles.AdjustToUniversal, out DateTime dt);
return dt;
}
public decimal GetDecimal(int i)
{
- return decimal.Parse(GetAttValue(i).N);
+ return decimal.Parse(GetAttValueN(i));
}
public double GetDouble(int i)
{
- return double.Parse(GetAttValue(i).N);
+ return double.Parse(GetAttValueN(i));
}
public Type GetFieldType(int i)
{
- throw new NotImplementedException();
+ return selectList[i].GetValue(DynamoDBConnection.NewServiceContext(), currentEntry).GetType();
}
public float GetFloat(int i)
{
- return float.Parse(GetAttValue(i).N);
+ return float.Parse(GetAttValueN(i));
}
public Guid GetGuid(int i)
@@ -193,18 +188,18 @@ public Guid GetGuid(int i)
public short GetInt16(int i)
{
- return short.Parse(GetAttValue(i).N);
+ return short.Parse(GetAttValueN(i));
}
public int GetInt32(int i)
{
- return int.Parse(GetAttValue(i).N);
+ return int.Parse(GetAttValueN(i));
}
public long GetInt64(int i)
{
- return long.Parse(GetAttValue(i).N);
+ return long.Parse(GetAttValueN(i));
}
public string GetName(int i)
@@ -214,14 +209,11 @@ public string GetName(int i)
public int GetOrdinal(string name)
{
- int j = 0;
- foreach (var col in Items[mCurrentPosition])
- {
- if (col.Key.ToLower() == name.ToLower())
- return j;
- j++;
- }
- throw new ArgumentOutOfRangeException(nameof(name));
+ CheckCurrentPosition();
+ int ordinal = currentEntry.CurrentRow.ToList().FindIndex(col => col.Key.ToLower() == name.ToLower());
+ if (ordinal == -1)
+ throw new ArgumentOutOfRangeException(nameof(name));
+ else return ordinal;
}
public DataTable GetSchemaTable()
@@ -231,7 +223,7 @@ public DataTable GetSchemaTable()
public string GetString(int i)
{
- return GetAttValue(i).S;
+ return DynamoDBHelper.GetString(GetAttValue(i));
}
public object GetValue(int i)
@@ -242,16 +234,13 @@ public object GetValue(int i)
if (attValue.IsBOOLSet)
{
value = attValue.BOOL;
- }
- if (attValue.S != null)
+ }else if (attValue.S != null || attValue.IsLSet || attValue.IsMSet)
{
- value = attValue.S;
- }
- if (attValue.N != null)
+ value = DynamoDBHelper.GetString(attValue);
+ }else if (attValue.N != null)
{
value = attValue.N;
- }
- if (attValue.B != null)
+ }else if (attValue.B != null)
{
value = attValue.B;
}
@@ -260,9 +249,11 @@ public object GetValue(int i)
private AttributeValue GetAttValue(int i)
{
- return (AttributeValue)selectList[i].GetValue(NewServiceContext(), new DynamoDBRecordEntry(Items[mCurrentPosition]));
+ return (AttributeValue)selectList[i].GetValue(DynamoDBConnection.NewServiceContext(), currentEntry);
}
+ private string GetAttValueN(int i) => GetAttValue(i)?.N ?? "0";
+
public int GetValues(object[] values)
{
System.Diagnostics.Debug.Assert(selectList.Length == values.Length, "Values mismatch");
@@ -281,12 +272,15 @@ public bool IsDBNull(int i)
public bool NextResult()
{
mCurrentPosition++;
- return (mCurrentPosition < ItemCount);
+ currentEntry = (mCurrentPosition < ItemCount) ? new DynamoDBRecordEntry(Items[mCurrentPosition]) : null;
+ return currentEntry != null;
}
public bool Read()
- {
- if (mCurrentPosition == ItemCount && mCurrentPosition > 0)
+ {
+ if (NextResult())
+ return true;
+ else if (mCurrentPosition > 0 && mResponse.LastEvaluatedKey?.Count > 0)
{
mResponse = mRequest.Read(mResponse.LastEvaluatedKey);
/*
@@ -295,15 +289,11 @@ public bool Read()
* The result set contains the last_evaluated_key field. If more data is available for the operation,
* this key contains information about the last evaluated key. Otherwise, the key remains empty.
* */
+ mCurrentPosition = -1;
+ return NextResult();
}
- mCurrentPosition++;
- return (mCurrentPosition < ItemCount);
+ return false;
}
- internal IOServiceContext NewServiceContext()
- {
- return null;
- }
-
}
public class GxDynamoDBCacheDataReader : GxCacheDataReader
@@ -316,8 +306,7 @@ public GxDynamoDBCacheDataReader(CacheItem cacheItem, bool computeSize, string k
public override DateTime GetDateTime(int i)
{
- DateTime dt = new DateTime();
- DateTime.TryParse(GetAttValue(i).S, out dt);
+ DateTime.TryParse(GetAttValue(i).S, null, DateTimeStyles.AdjustToUniversal, out DateTime dt);
return dt;
}
@@ -325,42 +314,46 @@ private AttributeValue GetAttValue(int i)
{
return (AttributeValue)block.Item(pos, i);
}
-
+ private string GetAttValueN(int i) => GetAttValue(i)?.N ?? "0";
public override decimal GetDecimal(int i)
{
- return decimal.Parse(GetAttValue(i).N);
+ return decimal.Parse(GetAttValueN(i));
}
-
public override short GetInt16(int i)
{
- return short.Parse(GetAttValue(i).N);
+ return short.Parse(GetAttValueN(i));
}
public override int GetInt32(int i)
{
- return int.Parse(GetAttValue(i).N);
+ return int.Parse(GetAttValueN(i));
}
public override long GetInt64(int i)
{
- return long.Parse(GetAttValue(i).N);
+ return long.Parse(GetAttValueN(i));
}
public override string GetString(int i)
{
- return GetAttValue(i).S;
+ return DynamoDBHelper.GetString(GetAttValue(i));
}
public override bool GetBoolean(int i)
{
- return GetAttValue(i).IsBOOLSet;
+ AttributeValue value = GetAttValue(i);
+ return value.IsBOOLSet && value.BOOL;
}
public override long GetBytes(int i, long fieldOffset, byte[] buffer, int bufferoffset, int length)
{
- throw new NotImplementedException();
+ MemoryStream ms = GetAttValue(i).B;
+ if (ms == null)
+ return 0;
+ ms.Seek(fieldOffset, SeekOrigin.Begin);
+ return ms.Read(buffer, bufferoffset, length);
}
}
}
diff --git a/dotnet/src/dotnetcommon/DynService.Dynamo/DynamoDBDataStoreHelper.cs b/dotnet/src/dotnetcommon/DynService.Dynamo/DynamoDBDataStoreHelper.cs
new file mode 100644
index 000000000..0c3cb20b8
--- /dev/null
+++ b/dotnet/src/dotnetcommon/DynService.Dynamo/DynamoDBDataStoreHelper.cs
@@ -0,0 +1,109 @@
+using GeneXus.Data.Dynamo;
+using GeneXus.Utils;
+using System;
+using System.Collections.Generic;
+
+namespace GeneXus.Data.NTier
+{
+ public class DynamoDBDataStoreHelper: DynServiceDataStoreHelperBase
+ {
+
+ public DynamoQuery NewQuery() => new DynamoQuery(this);
+ public DynamoQuery NewScan() => new DynamoScan(this);
+
+ public DynamoDBMap Map(string name)
+ {
+ return new DynamoDBMap(name);
+ }
+
+ public object empty(GXType gxtype)
+ {
+ switch(gxtype)
+ {
+ case GXType.Number:
+ case GXType.Int16:
+ case GXType.Int32:
+ case GXType.Int64: return 0;
+ case GXType.Date:
+ case GXType.DateTime:
+ case GXType.DateTime2: return DateTimeUtil.NullDate();
+ case GXType.Byte:
+ case GXType.NChar:
+ case GXType.NClob:
+ case GXType.NVarChar:
+ case GXType.Char:
+ case GXType.LongVarChar:
+ case GXType.Clob:
+ case GXType.VarChar:
+ case GXType.Raw:
+ case GXType.Blob: return string.Empty;
+ case GXType.Boolean: return false;
+ case GXType.Decimal: return 0f;
+ case GXType.NText:
+ case GXType.Text:
+ case GXType.Image:
+ case GXType.UniqueIdentifier:
+ case GXType.Xml: return string.Empty;
+ case GXType.Geography:
+ case GXType.Geopoint:
+ case GXType.Geoline:
+ case GXType.Geopolygon: return new Geospatial();
+ case GXType.DateAsChar: return string.Empty;
+ case GXType.Undefined:
+ default: return null;
+
+ }
+ }
+ }
+
+ public static class DynamoFluentExtensions
+ {
+ public static Query OrderBy(this Query dynamoQuery, string index)
+ {
+ return (dynamoQuery as DynamoQuery)?.OrderBy(index);
+ }
+ public static Query SetKey(this Query dynamoQuery, string partitionKey)
+ {
+ return (dynamoQuery as DynamoQuery)?.SetKey(partitionKey);
+ }
+ public static Query KeyFilter(this Query dynamoQuery, string[] filters)
+ {
+ return (dynamoQuery as DynamoQuery)?.KeyFilter(filters);
+ }
+ }
+
+ public class DynamoQuery : Query
+ {
+ public string Index { get; set; }
+ public bool ScanIndexForward = true;
+ private const string RANGE_KEY_INDEX = "RangeKey";
+ private static readonly char[] indexTrimChars = new char[] { '(', ')' };
+
+ public DynamoQuery OrderBy(string index)
+ {
+ if(index.StartsWith("(", StringComparison.InvariantCulture))
+ {
+ ScanIndexForward = false;
+ index = index.Trim(indexTrimChars);
+ }
+ if (index != RANGE_KEY_INDEX)
+ Index = index;
+ return this;
+ }
+
+ public string PartitionKey { get; private set; }
+ public DynamoQuery SetKey(string partitionKey)
+ {
+ PartitionKey = partitionKey;
+ return this;
+ }
+ internal IEnumerable KeyFilters { get; set; } = Array.Empty();
+ public DynamoQuery KeyFilter(string[] filters)
+ {
+ KeyFilters = filters;
+ return this;
+ }
+
+ public DynamoQuery(DynamoDBDataStoreHelper dataStoreHelper) : base(dataStoreHelper) { }
+ }
+}
diff --git a/dotnet/src/dotnetcommon/DynService.Dynamo/DynamoDBHelper.cs b/dotnet/src/dotnetcommon/DynService.Dynamo/DynamoDBHelper.cs
new file mode 100644
index 000000000..4aa4789ce
--- /dev/null
+++ b/dotnet/src/dotnetcommon/DynService.Dynamo/DynamoDBHelper.cs
@@ -0,0 +1,153 @@
+using Amazon.DynamoDBv2.Model;
+using GeneXus.Data.NTier;
+using GeneXus.Utils;
+using System;
+using System.Collections.Generic;
+using System.Data;
+using System.IO;
+using System.Linq;
+using System.Text;
+#if NETCORE
+using System.Threading;
+using System.Threading.Tasks;
+#endif
+
+namespace GeneXus.Data.Dynamo
+{
+ internal class DynamoDBHelper
+ {
+#if NETCORE
+ private static readonly TaskFactory mTaskFactory = new
+ TaskFactory(CancellationToken.None,
+ TaskCreationOptions.None,
+ TaskContinuationOptions.None,
+ TaskScheduler.Default);
+ internal static TResult RunSync(Func> func) => mTaskFactory.StartNew>(func).Unwrap().GetAwaiter().GetResult();
+#endif
+
+ internal static AttributeValue ToAttributeValue(VarValue var)
+ {
+ return ToAttributeValue(GxService.GXTypeToDbType(var.Type), var.Value);
+ }
+
+ internal static void GXToDynamoQueryParameter(Dictionary dynParm, ServiceParameter parm) => AddAttributeValue($":{ parm.ParameterName }", dynParm, parm);
+
+ internal static bool AddAttributeValue(string parmName, string fromName, Dictionary values, IDataParameterCollection parms, IEnumerable queryVars)
+ {
+ if(!AddAttributeValue(parmName, values, parms[fromName] as ServiceParameter))
+ {
+ VarValue varValue = queryVars.FirstOrDefault(v => v.Name == $":{fromName}");
+ if (varValue != null)
+ values[parmName] = DynamoDBHelper.ToAttributeValue(varValue);
+ return varValue != null;
+ }
+ return true;
+ }
+
+ internal static bool AddAttributeValue(string parmName, Dictionary dynParm, ServiceParameter parm)
+ {
+ if (parm == null)
+ return false;
+ AttributeValue value = ToAttributeValue(parm.DbType, parm.Value);
+ if (value != null)
+ {
+ dynParm[parmName] = value;
+ return true;
+ }
+ return false;
+ }
+
+ internal static AttributeValue ToAttributeValue(DbType dbType, Object value)
+ {
+ AttributeValue attValue;
+ switch (dbType)
+ {
+ case DbType.Binary:
+ if (value is byte[] valueArr)
+ {
+ attValue = new AttributeValue
+ {
+ B = new MemoryStream(valueArr)
+ };
+ break;
+ }
+ else throw new ArgumentException("Required value not found");
+ case DbType.Boolean:
+ case DbType.Byte:
+ attValue = new AttributeValue
+ {
+ BOOL = (bool)value
+ };
+ break;
+ case DbType.Time:
+ case DbType.Date:
+ attValue = new AttributeValue
+ {
+ S = DateTime.SpecifyKind((DateTime)value, DateTimeKind.Utc).ToString("yyyy-MM-dd")
+ };
+ break;
+ case DbType.DateTime2:
+ case DbType.DateTime:
+ attValue = new AttributeValue
+ {
+ S = DateTime.SpecifyKind((DateTime)value, DateTimeKind.Utc).ToString("yyyy-MM-ddTHH:mm:ssK")
+ };
+ break;
+
+
+ case DbType.UInt16:
+ case DbType.UInt32:
+ case DbType.UInt64:
+ case DbType.VarNumeric:
+ case DbType.Decimal:
+ case DbType.Double:
+ case DbType.Int16:
+ case DbType.Int32:
+ case DbType.Int64:
+ attValue = new AttributeValue
+ {
+ N = value.ToString()
+ };
+ break;
+ default:
+ string valueS = value.ToString().Replace("%", string.Empty);
+ attValue = new AttributeValue
+ {
+ S = valueS
+ };
+ break;
+ }
+ return attValue;
+ }
+
+ public static string GetString(AttributeValue attValue)
+ {
+ string value = attValue.S;
+ if (value != null)
+ return value;
+ else if (attValue.NS.Count > 0)
+ return SetToString(attValue.NS);
+ else if (attValue.SS.Count > 0)
+ return SetToString(attValue.SS);
+ else if (attValue.IsBOOLSet)
+ return $"{ attValue.BOOL }";
+ else if (attValue.IsMSet)
+ return JSONHelper.Serialize(ConvertToDictionary(attValue.M), Encoding.UTF8);
+ else if (attValue.IsLSet)
+ return JSONHelper.Serialize>(attValue.L.Select(item => GetString(item)).ToList());
+ return null;
+ }
+
+ private static Dictionary ConvertToDictionary(Dictionary m)
+ {
+ Dictionary dict = new Dictionary();
+ foreach (KeyValuePair keyValues in m)
+ {
+ dict.Add(keyValues.Key, GetString(keyValues.Value));
+ }
+ return dict;
+ }
+
+ private static string SetToString(List nS) => $"[ { string.Join(", ", nS) } ]";
+ }
+}
diff --git a/dotnet/src/dotnetframework/DynService.Dynamo/DynamoDBMaps.cs b/dotnet/src/dotnetcommon/DynService.Dynamo/DynamoDBMaps.cs
similarity index 58%
rename from dotnet/src/dotnetframework/DynService.Dynamo/DynamoDBMaps.cs
rename to dotnet/src/dotnetcommon/DynService.Dynamo/DynamoDBMaps.cs
index 63497aaf9..4c01e9d14 100644
--- a/dotnet/src/dotnetframework/DynService.Dynamo/DynamoDBMaps.cs
+++ b/dotnet/src/dotnetcommon/DynService.Dynamo/DynamoDBMaps.cs
@@ -2,30 +2,27 @@
using GeneXus.Data.NTier;
using System;
using System.Collections.Generic;
-using System.Diagnostics;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
namespace GeneXus.Data.Dynamo
{
public class DynamoDBMap : Map
{
-
- public DynamoDBMap(string name): base(name)
- {
+ internal bool NeedsAttributeMap { get; }
+ public DynamoDBMap(string name): base(RemoveSharp(name))
+ {
+ NeedsAttributeMap = name.StartsWith("#", StringComparison.InvariantCulture);
}
+ private static string RemoveSharp(string name) => name.StartsWith("#", StringComparison.InvariantCulture) ? name.Substring(1) : name;
public override object GetValue(IOServiceContext context, RecordEntryRow currentEntry)
{
Dictionary values = ((DynamoDBRecordEntry)currentEntry).CurrentRow;
- AttributeValue val = null;
- values.TryGetValue(GetName(context), out val);
+ values.TryGetValue(GetName(context), out AttributeValue val);
return val;
}
- public override void SetValue(IOServiceContext context, RecordEntryRow currentEntry, object value)
+ public override void SetValue(RecordEntryRow currentEntry, object value)
{
throw new NotImplementedException();
}
diff --git a/dotnet/src/dotnetcommon/DynService.Dynamo/DynamoDBRequestWrapper.cs b/dotnet/src/dotnetcommon/DynService.Dynamo/DynamoDBRequestWrapper.cs
new file mode 100644
index 000000000..220b42b50
--- /dev/null
+++ b/dotnet/src/dotnetcommon/DynService.Dynamo/DynamoDBRequestWrapper.cs
@@ -0,0 +1,57 @@
+using System;
+using System.Collections.Generic;
+using Amazon.DynamoDBv2;
+using Amazon.DynamoDBv2.Model;
+#if NETCORE
+using GeneXus.Data.Dynamo;
+#endif
+
+namespace GeneXus.Data.NTier.DynamoDB
+{
+ public class RequestWrapper
+ {
+ private readonly AmazonDynamoDBClient mDynamoDB;
+ private readonly AmazonDynamoDBRequest mReq;
+
+ public RequestWrapper(AmazonDynamoDBClient mDynamoDB, AmazonDynamoDBRequest req)
+ {
+ this.mDynamoDB = mDynamoDB;
+ this.mReq = req;
+ }
+
+ public ResponseWrapper Read()
+ {
+ return Read(null);
+ }
+
+ public ResponseWrapper Read(Dictionary lastEvaluatedKey)
+ {
+ if (mReq is ScanRequest scanReq)
+ {
+ scanReq.ExclusiveStartKey = lastEvaluatedKey;
+#if NETCORE
+ ScanResponse scanResponse = DynamoDBHelper.RunSync(() => mDynamoDB.ScanAsync(scanReq));
+#else
+ ScanResponse scanResponse = mDynamoDB.Scan(scanReq);
+#endif
+ return new ResponseWrapper(scanResponse);
+ }
+ if (mReq is QueryRequest queryReq)
+ {
+ queryReq.ExclusiveStartKey = lastEvaluatedKey;
+#if NETCORE
+ QueryResponse queryResponse = DynamoDBHelper.RunSync(() => mDynamoDB.QueryAsync(queryReq));
+#else
+ QueryResponse queryResponse = mDynamoDB.Query(queryReq);
+#endif
+ return new ResponseWrapper(queryResponse);
+ }
+ throw new NotImplementedException();
+ }
+
+ internal void Close()
+ {
+ mDynamoDB.Dispose();
+ }
+ }
+}
diff --git a/dotnet/src/dotnetframework/DynService.Dynamo/DynamoDBResponseWrapper.cs b/dotnet/src/dotnetcommon/DynService.Dynamo/DynamoDBResponseWrapper.cs
similarity index 89%
rename from dotnet/src/dotnetframework/DynService.Dynamo/DynamoDBResponseWrapper.cs
rename to dotnet/src/dotnetcommon/DynService.Dynamo/DynamoDBResponseWrapper.cs
index 59024cea7..1aacb128e 100644
--- a/dotnet/src/dotnetframework/DynService.Dynamo/DynamoDBResponseWrapper.cs
+++ b/dotnet/src/dotnetcommon/DynService.Dynamo/DynamoDBResponseWrapper.cs
@@ -1,9 +1,5 @@
using Amazon.DynamoDBv2.Model;
-using System;
using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
namespace GeneXus.Data.NTier.DynamoDB
{
diff --git a/dotnet/src/dotnetcommon/DynService.Dynamo/DynamoDBScan.cs b/dotnet/src/dotnetcommon/DynService.Dynamo/DynamoDBScan.cs
new file mode 100644
index 000000000..080802b72
--- /dev/null
+++ b/dotnet/src/dotnetcommon/DynService.Dynamo/DynamoDBScan.cs
@@ -0,0 +1,10 @@
+namespace GeneXus.Data.NTier
+{
+ public class DynamoScan : DynamoQuery
+ {
+ public DynamoScan(DynamoDBDataStoreHelper dataStoreHelper):base(dataStoreHelper)
+ {
+
+ }
+ }
+}
diff --git a/dotnet/src/dotnetframework/DynService.Dynamo/Properties/AssemblyInfo.cs b/dotnet/src/dotnetcommon/DynService.Dynamo/Properties/AssemblyInfo.cs
similarity index 100%
rename from dotnet/src/dotnetframework/DynService.Dynamo/Properties/AssemblyInfo.cs
rename to dotnet/src/dotnetcommon/DynService.Dynamo/Properties/AssemblyInfo.cs
diff --git a/dotnet/src/dotnetcore/DynService/Dynamo/DynService.DynamoDB.csproj b/dotnet/src/dotnetcore/DynService/Dynamo/DynService.DynamoDB.csproj
new file mode 100644
index 000000000..7756884cb
--- /dev/null
+++ b/dotnet/src/dotnetcore/DynService/Dynamo/DynService.DynamoDB.csproj
@@ -0,0 +1,34 @@
+
+
+ net5.0;net6.0
+ NETCORE
+ GeneXus.Data.NTier
+ GeneXus.Data.DynService.DynamoDB
+ false
+ DynamoDB
+ GeneXus.DynService.DynamoDB
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
\ No newline at end of file
diff --git a/dotnet/src/dotnetcore/DynService/OData/DynServiceOData.csproj b/dotnet/src/dotnetcore/DynService/OData/DynServiceOData.csproj
index 9e144b035..0f3e48a31 100644
--- a/dotnet/src/dotnetcore/DynService/OData/DynServiceOData.csproj
+++ b/dotnet/src/dotnetcore/DynService/OData/DynServiceOData.csproj
@@ -16,7 +16,7 @@
-
+
diff --git a/dotnet/src/dotnetframework/DynService.Core/DynService.Core.csproj b/dotnet/src/dotnetframework/DynService.Core/DynService.Core.csproj
deleted file mode 100644
index 72410d78f..000000000
--- a/dotnet/src/dotnetframework/DynService.Core/DynService.Core.csproj
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
- net462
- GeneXus.Data.NTier
- GeneXus.Data.DynService.Core
- CA1812
- Dynservice
- GeneXus.DynService.Core
-
-
-
-
-
\ No newline at end of file
diff --git a/dotnet/src/dotnetframework/DynService.Core/GlobalSuppressions.cs b/dotnet/src/dotnetframework/DynService.Core/GlobalSuppressions.cs
deleted file mode 100644
index 292ccd6ae..000000000
--- a/dotnet/src/dotnetframework/DynService.Core/GlobalSuppressions.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-// This file is used by Code Analysis to maintain SuppressMessage
-// attributes that are applied to this project.
-// Project-level suppressions either have no target or are given
-// a specific target and scoped to a namespace, type, member, etc.
-
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Performance", "CA1819:Properties should not return arrays", Justification = "", Scope = "member", Target = "~P:GeneXus.Data.NTier.Query.AssignAtts")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Performance", "CA1819:Properties should not return arrays", Justification = "", Scope = "member", Target = "~P:GeneXus.Data.NTier.Query.Filters")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Performance", "CA1819:Properties should not return arrays", Justification = "", Scope = "member", Target = "~P:GeneXus.Data.NTier.Query.OrderBys")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Performance", "CA1819:Properties should not return arrays", Justification = "", Scope = "member", Target = "~P:GeneXus.Data.NTier.Query.Projection")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Performance", "CA1819:Properties should not return arrays", Justification = "", Scope = "member", Target = "~P:GeneXus.Data.NTier.Query.SelectList")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Performance", "CA1819:Properties should not return arrays", Justification = "", Scope = "member", Target = "~P:GeneXus.Data.NTier.Query.Vars")]
-[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Performance", "CA1819:Properties should not return arrays", Justification = "", Scope = "member", Target = "~P:GeneXus.Data.NTier.QueryExpression.Select")]
diff --git a/dotnet/src/dotnetframework/DynService.Dynamo/DynService.DynamoDB.csproj b/dotnet/src/dotnetframework/DynService.Dynamo/DynService.DynamoDB.csproj
deleted file mode 100644
index 41d1c00ce..000000000
--- a/dotnet/src/dotnetframework/DynService.Dynamo/DynService.DynamoDB.csproj
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
- net462
- GeneXus.Data.NTier
- GeneXus.Data.DynService.DynamoDB
- false
- DynamoDB
- GeneXus.DynService.DynamoDB
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/dotnet/src/dotnetframework/DynService.Dynamo/DynamoDBConnection.cs b/dotnet/src/dotnetframework/DynService.Dynamo/DynamoDBConnection.cs
deleted file mode 100644
index 72247b237..000000000
--- a/dotnet/src/dotnetframework/DynService.Dynamo/DynamoDBConnection.cs
+++ /dev/null
@@ -1,226 +0,0 @@
-using Amazon;
-using Amazon.DynamoDBv2;
-using Amazon.DynamoDBv2.Model;
-using Amazon.Runtime;
-using GeneXus.Data.Dynamo;
-using GeneXus.Data.NTier.DynamoDB;
-using System;
-using System.Collections.Generic;
-using System.Data;
-using System.Data.Common;
-using System.Text.RegularExpressions;
-using System.Linq;
-using GeneXus.Cache;
-
-namespace GeneXus.Data.NTier
-{
-
- public class DynamoDBService: GxService
- {
- public DynamoDBService(string id, string providerId): base(id, providerId, typeof(DynamoDBConnection))
- {
-
- }
-
- public override IDataReader GetCacheDataReader(CacheItem item, bool computeSize, string keyCache)
- {
- return new GxDynamoDBCacheDataReader(item, computeSize, keyCache);
- }
- }
-
- public class DynamoDBConnection : ServiceConnection
- {
- private readonly string CLIENT_ID = "User Id";
- private readonly string CLIENT_SECRET = "password";
- private readonly string REGION = "region";
- private AmazonDynamoDBClient mDynamoDB;
- private AWSCredentials mCredentials;
- private RegionEndpoint mRegion = RegionEndpoint.USEast1;
-
- public override string ConnectionString
- {
- get { return base.ConnectionString; }
-
- set
- {
- base.ConnectionString = value;
- }
- }
-
- private void InitializeDBConnection()
- {
-
- DbConnectionStringBuilder builder = new DbConnectionStringBuilder(false);
- builder.ConnectionString = this.ConnectionString;
- if (builder.TryGetValue(CLIENT_ID, out object clientId) && builder.TryGetValue(CLIENT_SECRET, out object clientSecret))
- {
- mCredentials = new BasicAWSCredentials(clientId.ToString(), clientSecret.ToString());
- }
- if (builder.TryGetValue(REGION, out object region))
- {
- mRegion = RegionEndpoint.GetBySystemName(region.ToString());
- }
- }
- private bool Initialize()
- {
- InitializeDBConnection();
- State = ConnectionState.Executing;
- mDynamoDB = new Amazon.DynamoDBv2.AmazonDynamoDBClient(mCredentials, mRegion);
- return true;
- }
-
- public override int ExecuteNonQuery(ServiceCursorDef cursorDef, IDataParameterCollection parms, CommandBehavior behavior)
- {
- Initialize();
- Query query = cursorDef.Query as Query;
-
- Dictionary values = new Dictionary();
- if (parms.Count > 0)
- {
- for (int i = 0; i < parms.Count; i++)
- {
- ServiceParameter parm = parms[i] as ServiceParameter;
- DynamoDBHelper.GXToDynamoQueryParameter("", values, parm);
- }
- }
- var pattern = @"\((.*) = :(.*)\)";
- Dictionary keyCondition = new Dictionary();
- List filters = new List();
-
- foreach (var keyFilter in query.Filters)
- {
- var match = Regex.Match(keyFilter, pattern);
- String varName = match.Groups[2].Value;
- if (match.Groups.Count > 1)
- {
- keyCondition[match.Groups[1].Value] = values[varName];
- }
- }
- AmazonDynamoDBRequest request = null;
-
- switch (query.CursorType)
- {
- case ServiceCursorDef.CursorType.Select:
- throw new NotImplementedException();
-
- case ServiceCursorDef.CursorType.Delete:
- request = new DeleteItemRequest()
- {
- TableName = query.TableName,
- Key = keyCondition
- };
- mDynamoDB.DeleteItem((DeleteItemRequest)request);
-
- break;
- case ServiceCursorDef.CursorType.Insert:
- request = new PutItemRequest
- {
- TableName = query.TableName,
- Item = values
- };
- mDynamoDB.PutItem((PutItemRequest)request);
- break;
- case ServiceCursorDef.CursorType.Update:
- request = new UpdateItemRequest
- {
- TableName = query.TableName,
- Key = keyCondition,
- AttributeUpdates = ToAttributeUpdates(keyCondition, values)
-
- };
- mDynamoDB.UpdateItem((UpdateItemRequest)request);
- break;
-
- default:
- break;
- }
-
- return 0;
- }
-
- private Dictionary ToAttributeUpdates(Dictionary keyConditions, Dictionary values)
- {
- Dictionary updates = new Dictionary();
- foreach (var item in values)
- {
- if (!keyConditions.ContainsKey(item.Key) && !item.Key.StartsWith("AV"))
- {
- updates[item.Key] = new AttributeValueUpdate(item.Value, AttributeAction.PUT);
- }
- }
- return updates;
- }
-
- public override IDataReader ExecuteReader(ServiceCursorDef cursorDef, IDataParameterCollection parms, CommandBehavior behavior)
- {
-
- Initialize();
- Query query = cursorDef.Query as Query;
- Dictionary valuesAux = new Dictionary();
- Dictionary values = new Dictionary();
- if (parms.Count > 0)
- {
- for (int i = 0; i < parms.Count; i++)
- {
- ServiceParameter parm = parms[i] as ServiceParameter;
- DynamoDBHelper.GXToDynamoQueryParameter(":", values, parm);
- }
- }
-
- List filtersAux = new List();
- List filters = new List();
-
- filters.AddRange(query.Filters);
-
- foreach (var item in query.Vars)
- {
- values.Add(item.Name, DynamoDBHelper.ToAttributeValue(item));
- }
-
- try
- {
- DynamoDBDataReader dataReader;
- AmazonDynamoDBRequest req;
- CreateDynamoQuery(query, values, filters.ToArray(), out dataReader, out req);
- RequestWrapper reqWrapper = new RequestWrapper(mDynamoDB, req);
- dataReader = new DynamoDBDataReader(cursorDef, reqWrapper, parms);
- return dataReader;
- }
- catch (AmazonDynamoDBException e) { throw e; }
- catch (AmazonServiceException e) { throw e; }
- catch (Exception e) { throw e; }
- }
-
- private static void CreateDynamoQuery(Query query, Dictionary values, String[] queryFilters, out DynamoDBDataReader dataReader, out AmazonDynamoDBRequest req)
- {
- dataReader = null;
- req = null;
- if (query is Scan)
- {
- req = new ScanRequest
- {
- TableName = query.TableName,
- ProjectionExpression = String.Join(",", query.Projection),
-
- };
- if (queryFilters.Length > 0)
- {
- ((ScanRequest)req).FilterExpression = String.Join(" AND ", queryFilters);
- ((ScanRequest)req).ExpressionAttributeValues = values;
- }
- }
- else
- {
- req = new QueryRequest
- {
- TableName = query.TableName,
- KeyConditionExpression = String.Join(" AND ", query.Filters),
- ExpressionAttributeValues = values,
- ProjectionExpression = String.Join(",", query.Projection),
-
- };
- }
- }
-
- }
-}
diff --git a/dotnet/src/dotnetframework/DynService.Dynamo/DynamoDBDataStoreHelper.cs b/dotnet/src/dotnetframework/DynService.Dynamo/DynamoDBDataStoreHelper.cs
deleted file mode 100644
index 86d97da9f..000000000
--- a/dotnet/src/dotnetframework/DynService.Dynamo/DynamoDBDataStoreHelper.cs
+++ /dev/null
@@ -1,20 +0,0 @@
-using GeneXus.Data.Dynamo;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace GeneXus.Data.NTier
-{
- public class DynamoDBDataStoreHelper: DataStoreHelperBase
- {
-
- public DynamoDBMap Map(string name)
- {
- return new DynamoDBMap(name);
- }
- }
-
-
-}
diff --git a/dotnet/src/dotnetframework/DynService.Dynamo/DynamoDBHelper.cs b/dotnet/src/dotnetframework/DynService.Dynamo/DynamoDBHelper.cs
deleted file mode 100644
index 6a66c2fea..000000000
--- a/dotnet/src/dotnetframework/DynService.Dynamo/DynamoDBHelper.cs
+++ /dev/null
@@ -1,80 +0,0 @@
-using Amazon.DynamoDBv2.Model;
-using GeneXus.Data.NTier;
-using System;
-using System.Collections.Generic;
-using System.Data;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace GeneXus.Data.Dynamo
-{
- internal class DynamoDBHelper
- {
- internal static AttributeValue ToAttributeValue(VarValue var)
- {
- return ToAttributeValue(GxService.GXTypeToDbType(var.Type), var.Value, false);
- }
-
- internal static void GXToDynamoQueryParameter(string prefix, Dictionary dynParm, ServiceParameter parm)
- {
- AttributeValue v = ToAttributeValue(parm.DbType, parm.Value, true);
- if (v != null)
- dynParm[$"{prefix}{parm.ParameterName}"] = v;
- }
-
- private static AttributeValue ToAttributeValue(DbType dbType, Object value, bool skipEmpty)
- {
- AttributeValue attValue = null;
- switch (dbType)
- {
- case System.Data.DbType.Binary:
- throw new NotImplementedException("Binary column not implemented yet");
- case System.Data.DbType.Boolean:
- case System.Data.DbType.Byte:
- attValue = new AttributeValue
- {
- BOOL = (bool)value
- };
- break;
- case System.Data.DbType.Time:
- case System.Data.DbType.Date:
- case System.Data.DbType.DateTime2:
- case System.Data.DbType.DateTime:
- attValue = new AttributeValue
- {
- S = value.ToString()
- };
- break;
-
-
- case System.Data.DbType.UInt16:
- case System.Data.DbType.UInt32:
- case System.Data.DbType.UInt64:
- case System.Data.DbType.VarNumeric:
- case System.Data.DbType.Decimal:
- case System.Data.DbType.Double:
- case System.Data.DbType.Int16:
- case System.Data.DbType.Int32:
- case System.Data.DbType.Int64:
- attValue = new AttributeValue
- {
- N = value.ToString()
- };
- break;
- default:
- //DynamoDB does not support empty values
- string valueS = value.ToString().Replace("%", string.Empty);
- if (!string.IsNullOrEmpty(valueS))
- {
- attValue = new AttributeValue
- {
- S = valueS
- };
- }
- break;
- }
- return attValue;
- }
- }
-}
diff --git a/dotnet/src/dotnetframework/DynService.Dynamo/DynamoDBRequestWrapper.cs b/dotnet/src/dotnetframework/DynService.Dynamo/DynamoDBRequestWrapper.cs
deleted file mode 100644
index d123627b5..000000000
--- a/dotnet/src/dotnetframework/DynService.Dynamo/DynamoDBRequestWrapper.cs
+++ /dev/null
@@ -1,52 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using Amazon.DynamoDBv2;
-using Amazon.DynamoDBv2.Model;
-
-namespace GeneXus.Data.NTier.DynamoDB
-{
- public class RequestWrapper
- {
- private AmazonDynamoDBClient mDynamoDB;
- private AmazonDynamoDBRequest mReq;
-
- public RequestWrapper()
- {
-
- }
-
- public RequestWrapper(AmazonDynamoDBClient mDynamoDB, AmazonDynamoDBRequest req)
- {
- this.mDynamoDB = mDynamoDB;
- this.mReq = req;
- }
-
- public ResponseWrapper Read()
- {
- return Read(null);
- }
-
- public ResponseWrapper Read(Dictionary lastEvaluatedKey)
- {
- if (mReq is ScanRequest)
- {
- ((ScanRequest)mReq).ExclusiveStartKey = lastEvaluatedKey;
- return new ResponseWrapper(mDynamoDB.Scan((ScanRequest)mReq));
- }
- if (mReq is QueryRequest)
- {
- ((QueryRequest)mReq).ExclusiveStartKey = lastEvaluatedKey;
- return new ResponseWrapper(mDynamoDB.Query((QueryRequest)mReq));
- }
- throw new NotImplementedException();
- }
-
- internal void Close()
- {
- mDynamoDB.Dispose();
- }
- }
-}
diff --git a/dotnet/src/dotnetframework/DynService.Dynamo/DynamoDBScan.cs b/dotnet/src/dotnetframework/DynService.Dynamo/DynamoDBScan.cs
deleted file mode 100644
index 9c1442355..000000000
--- a/dotnet/src/dotnetframework/DynService.Dynamo/DynamoDBScan.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace GeneXus.Data.NTier
-{
- public class Scan: Query
- {
- public Scan(object dataStoreHelper):base(dataStoreHelper)
- {
-
- }
- }
-}
diff --git a/dotnet/src/dotnetframework/DynServiceFabric/DynService.Fabric.csproj b/dotnet/src/dotnetframework/DynServiceFabric/DynService.Fabric.csproj
index cce2c76e6..e85f57197 100644
--- a/dotnet/src/dotnetframework/DynServiceFabric/DynService.Fabric.csproj
+++ b/dotnet/src/dotnetframework/DynServiceFabric/DynService.Fabric.csproj
@@ -1,4 +1,4 @@
-
+
net462
GeneXus.Data.DynService.Fabric
@@ -18,7 +18,7 @@
-
+
diff --git a/dotnet/src/dotnetframework/DynServiceFabric/FabricDataReader.cs b/dotnet/src/dotnetframework/DynServiceFabric/FabricDataReader.cs
index ebf7c4360..6025ad3e3 100644
--- a/dotnet/src/dotnetframework/DynServiceFabric/FabricDataReader.cs
+++ b/dotnet/src/dotnetframework/DynServiceFabric/FabricDataReader.cs
@@ -232,7 +232,7 @@ public int GetValues(object[] values)
{
System.Diagnostics.Debug.Assert(mResponse[mCurrentPosition].Values.Count == values.Length, "Values mismatch");
int i = 0;
- foreach (var attName in mProjection)
+ foreach (string attName in mProjection)
{
values[i] = mResponse[mCurrentPosition][attName];
i++;
diff --git a/dotnet/src/dotnetframework/DynServiceOData/DynServiceOData.csproj b/dotnet/src/dotnetframework/DynServiceOData/DynServiceOData.csproj
index 906d0183c..ec1a4c6de 100644
--- a/dotnet/src/dotnetframework/DynServiceOData/DynServiceOData.csproj
+++ b/dotnet/src/dotnetframework/DynServiceOData/DynServiceOData.csproj
@@ -26,7 +26,7 @@
-
+
diff --git a/dotnet/src/dotnetframework/GxClasses/Data/GXDataNTierADO.cs b/dotnet/src/dotnetframework/GxClasses/Data/GXDataNTierADO.cs
index f593de63c..79d2d3cce 100644
--- a/dotnet/src/dotnetframework/GxClasses/Data/GXDataNTierADO.cs
+++ b/dotnet/src/dotnetframework/GxClasses/Data/GXDataNTierADO.cs
@@ -586,7 +586,7 @@ public void SetParameterMultimedia(int id, string parm, string multimediaParm)
//Second execution of Dataprovider that updates images, CategoryImage = calendar.Link(), image_gxi=https://chatteatest.s3.amazonaws.com/TestPGXReleased/Category/CategoryImage/calendar_dc0ca2d9335a484cbdc2d21fc7568af7.png, copy falla, multimediaUri = image_gxi;
#pragma warning disable SCS0018 // Path traversal: injection possible in {1} argument passed to '{0}'
public void SetParameterMultimedia(int id, string image_gxi, string image, string tableName, string fieldName)
-{
+ {
GXLogging.Debug(log, "SetParameterMultimedia image_gxi:", image_gxi + " image:" + image);
bool storageServiceEnabled = !string.IsNullOrEmpty(tableName) && !string.IsNullOrEmpty(fieldName) && (GXServices.Instance != null && GXServices.Instance.Get(GXServices.STORAGE_SERVICE) != null);
string imageUploadName=image;
diff --git a/dotnet/src/dotnetframework/GxClasses/Data/GXDataNTierService.cs b/dotnet/src/dotnetframework/GxClasses/Data/GXDataNTierService.cs
index b8a1ff5d5..4df83cb39 100644
--- a/dotnet/src/dotnetframework/GxClasses/Data/GXDataNTierService.cs
+++ b/dotnet/src/dotnetframework/GxClasses/Data/GXDataNTierService.cs
@@ -186,6 +186,8 @@ public static DbType GXTypeToDbType(GXType type)
return DbType.Object;
case GXType.Blob:
return DbType.Binary;
+ case GXType.Boolean:
+ return DbType.Boolean;
case GXType.Undefined:
default:
return DbType.Object;
diff --git a/dotnet/src/dotnetframework/GxClasses/View/GXWebControls.cs b/dotnet/src/dotnetframework/GxClasses/View/GXWebControls.cs
index 5beefb333..16b54116b 100644
--- a/dotnet/src/dotnetframework/GxClasses/View/GXWebControls.cs
+++ b/dotnet/src/dotnetframework/GxClasses/View/GXWebControls.cs
@@ -41,7 +41,7 @@ private static Type GetWebStdType(GeneXus.Application.IGxContext context)
}
}
#else
- var cname = "GxWebStd";
+ string cname = "GxWebStd";
string mainNamespace, className;
if (Config.GetValueOf("AppMainNamespace", out mainNamespace))
className = mainNamespace + "." + cname;
@@ -1658,7 +1658,7 @@ public override void FromJSONObject(dynamic Obj)
JArray jsonArrValues = (JArray)jsonObj["v"];
if (jsonArrValues != null)
{
- var idx = 1;
+ int idx = 1;
for (int i = 0; i < jsonArrValues.Count; i++)
{
JArray jsonItem = jsonArrValues.GetArray(i);