with and without parameters works

This commit is contained in:
Wolfgang Hottgenroth 2021-11-25 14:49:08 +01:00
parent 66d222e0bf
commit 10c3cab432
Signed by: wn
GPG Key ID: E49AF3B9EF6DD469
5 changed files with 163 additions and 88 deletions

View File

@ -1,3 +1,5 @@
#pragma warning disable 1591
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Runtime.Serialization; using System.Runtime.Serialization;
@ -7,39 +9,47 @@ using de.hottis.genericdatabaseapiservice.Models;
namespace de.hottis.genericdatabaseapiservice.Services { namespace de.hottis.genericdatabaseapiservice.Services {
public interface IDbService { public interface IDbService {
Task<List<T>> JustDoSomething<T>(string msg); Task<List<TOUT>> ReadBySelect<TIN, TOUT>(string selectStatement, TIN input);
} }
public class DbService : IDbService { public class DbService : IDbService {
async public Task<List<T>> JustDoSomething<T>(string msg) {
Console.WriteLine(msg);
var itemList = new List<T>();
async public Task<List<TOUT>> ReadBySelect<TIN, TOUT>(string selectStatement, TIN input) {
var itemList = new List<TOUT>();
using (var conn = new MySqlConnection("Server=172.16.10.18;User ID=apiservicetestdb;Password=geheim123;Database=apiservicetestdb")) { using (var conn = new MySqlConnection("Server=172.16.10.18;User ID=apiservicetestdb;Password=geheim123;Database=apiservicetestdb")) {
await conn.OpenAsync(); await conn.OpenAsync();
using (var cmd = conn.CreateCommand()) { using (var cmd = conn.CreateCommand()) {
// cmd.CommandText = "INSERT INTO test1 (txt, nr) VALUES (@txt, @nr)"; cmd.CommandText = selectStatement;
// cmd.Parameters.AddWithValue("txt", "txt1"); if (input != null){
// cmd.Parameters.AddWithValue("nr", 12); foreach (var propertyInfo in typeof(TIN).GetProperties()) {
// await cmd.ExecuteNonQueryAsync(); Console.WriteLine("Input Property name: {0} {1} ", propertyInfo.Name, propertyInfo.PropertyType);
cmd.CommandText = "SELECT id, txt, nr FROM test1"; var attributes = propertyInfo.GetCustomAttributes(typeof(DataMemberAttribute), true);
var dma = (DataMemberAttribute)attributes[0];
Console.WriteLine("Input DataMember name: {0} {1} ", dma.Name, dma.TypeId);
var value = propertyInfo.GetValue(input);
Console.WriteLine("Input Value: {0}", value);
cmd.Parameters.AddWithValue(dma.Name, propertyInfo.GetValue(input));
}
} else {
Console.WriteLine("no input data");
}
using (var reader = await cmd.ExecuteReaderAsync()) { using (var reader = await cmd.ExecuteReaderAsync()) {
while (await reader.ReadAsync()) { while (await reader.ReadAsync()) {
var item = Activator.CreateInstance<T>(); var item = Activator.CreateInstance<TOUT>();
foreach (var propertyInfo in typeof(T).GetProperties()) { foreach (var propertyInfo in typeof(TOUT).GetProperties()) {
Console.WriteLine("Property name: {0} {1} ", propertyInfo.Name, propertyInfo.PropertyType); Console.WriteLine("Output Property name: {0} {1} ", propertyInfo.Name, propertyInfo.PropertyType);
var attributes = propertyInfo.GetCustomAttributes(typeof(DataMemberAttribute), true); var attributes = propertyInfo.GetCustomAttributes(typeof(DataMemberAttribute), true);
var dma = (DataMemberAttribute)attributes[0]; var dma = (DataMemberAttribute)attributes[0];
Console.WriteLine("DataMember name: {0} {1} ", dma.Name, dma.TypeId); Console.WriteLine("Output DataMember name: {0} {1} ", dma.Name, dma.TypeId);
if (propertyInfo.PropertyType == typeof(System.String)) { if (propertyInfo.PropertyType == typeof(System.String)) {
propertyInfo.SetValue(item, reader.GetString(dma.Name)); propertyInfo.SetValue(item, reader.GetString(dma.Name));
Console.WriteLine("Value:{0}", reader.GetString(dma.Name)); Console.WriteLine("Output Value:{0}", reader.GetString(dma.Name));
} else if (propertyInfo.PropertyType == typeof(System.Int32)) { } else if (propertyInfo.PropertyType == typeof(System.Int32)) {
propertyInfo.SetValue(item, reader.GetInt32(dma.Name)); propertyInfo.SetValue(item, reader.GetInt32(dma.Name));
Console.WriteLine("Value:{0}", reader.GetInt32(dma.Name)); Console.WriteLine("Output Value:{0}", reader.GetInt32(dma.Name));
} }
} }
itemList.Add(item); itemList.Add(item);
@ -51,3 +61,5 @@ namespace de.hottis.genericdatabaseapiservice.Services {
} }
} }
} }
#pragma warning restore 1591

View File

@ -95,12 +95,14 @@ for path in apiDefinition['paths'].values():
if 'requestBody' in operation: if 'requestBody' in operation:
bodyInputTypeName = OpenApiExtractRefType(operation['requestBody']['content']['application/json']['schema']['$ref']) bodyInputTypeName = OpenApiExtractRefType(operation['requestBody']['content']['application/json']['schema']['$ref'])
bodyInputType = { 'apiName': bodyInputTypeName, 'csName': CsOperationNameConverter(bodyInputTypeName) } bodyInputType = { 'apiName': bodyInputTypeName, 'csName': CsOperationNameConverter(bodyInputTypeName) }
paramsInputTypes =[]
paramInputTypes = []
if 'parameters' in operation: if 'parameters' in operation:
for paramsInputType in operation['parameters']: for paramsInputType in operation['parameters']:
paramsInputType['type'] = CsTypeConverter(paramsInputType['schema']['type']) paramsInputType['type'] = CsTypeConverter(paramsInputType['schema']['type'])
del paramsInputType['schema'] del paramsInputType['schema']
paramsInputTypes.append(paramsInputType) paramsInputType['csName'] = CsOperationNameConverter(paramsInputType['name'])
paramInputTypes.append(paramsInputType)
operations.append({ operations.append({
@ -113,7 +115,7 @@ for path in apiDefinition['paths'].values():
'byIdSelector': operation['operationId'].endswith('byid'), 'byIdSelector': operation['operationId'].endswith('byid'),
'statement': statement, 'statement': statement,
'bodyInputType': bodyInputType, 'bodyInputType': bodyInputType,
'paramsInputTypes': paramsInputTypes 'paramInputTypes': paramInputTypes
}) })
#print(f"{operations=}") #print(f"{operations=}")
apiDefinition["operations"] = operations apiDefinition["operations"] = operations

View File

@ -4,14 +4,19 @@
REMOVE="0" REMOVE="0"
BUILD="0" BUILD="0"
EXECUTE="0" EXECUTE="0"
while getopts rxbh flag STAGE1="0"
STAGE2="0"
while getopts rxbh12 flag
do do
case "${flag}" in case "${flag}" in
h) h)
echo "1 ... generator stage 1 (implementation generator)";
echo "2 ... generator stage 2 (openapi generator)";
echo "r ... remove output directory"; echo "r ... remove output directory";
echo "b ... build after generating"; echo "b ... build after generating";
echo "x ... execute after building"; echo "x ... execute after building";
echo "h ... show help"; echo "h ... show help";
;; ;;
b) b)
BUILD="1" BUILD="1"
@ -22,6 +27,12 @@ do
x) x)
EXECUTE="1" EXECUTE="1"
;; ;;
1)
STAGE1="1"
;;
2)
STAGE2="1"
;;
esac esac
done done
@ -41,31 +52,38 @@ fi
# PACKAGE_NAME will be loaded here # PACKAGE_NAME will be loaded here
. ENV . ENV
echo "generate server code and endpoint stubs from openapi.yaml" if [ "$STAGE1" = "1" ]; then
docker run -it --rm -v $PWD:/work -u $UID openapitools/openapi-generator-cli:v5.3.0 \ echo "generate endpoint code from openapi.yaml"
generate -i /work/openapi.yaml -g aspnetcore -o /work/output \ python3.10 generate.py
--package-name $PACKAGE_NAME \ fi
--additional-properties="packageVersion=0.0.1,aspnetCoreVersion=5.0,operationIsAsync=false,operationResultTask=true,\
generateBody=false,classModifier=abstract,operationModifier=abstract"
echo "patch DbService registering into generated startup code" if [ "$STAGE2" = "1" ]; then
sed -i output/src/$PACKAGE_NAME/Startup.cs \ echo "generate server code and endpoint stubs from openapi.yaml"
-e 's#\(using '$PACKAGE_NAME'.OpenApi;\)#\1\n\n// added by post-processor\nusing '$PACKAGE_NAME'.Services;\n#' \ docker run -it --rm -v $PWD:/work -u $UID openapitools/openapi-generator-cli:v5.3.0 \
-e 's#^\([[:space:]]*\)\(// Add framework services.\)#\1// added by post-processor\n\1services.AddTransient<IDbService, DbService>();\n\n\1\2#' generate -i /work/openapi.yaml -g aspnetcore -o /work/output \
--package-name $PACKAGE_NAME \
--additional-properties="packageVersion=0.0.1,aspnetCoreVersion=5.0,operationIsAsync=false,operationResultTask=true,\
generateBody=false,classModifier=abstract,operationModifier=abstract"
echo "create directories for manually developed code" echo "patch DbService registering into generated startup code"
mkdir output/src/$PACKAGE_NAME/Implementations sed -i output/src/$PACKAGE_NAME/Startup.cs \
mkdir output/src/$PACKAGE_NAME/Services -e 's#\(using '$PACKAGE_NAME'.OpenApi;\)#\1\n\n// added by post-processor\nusing '$PACKAGE_NAME'.Services;\n#' \
-e 's#^\([[:space:]]*\)\(// Add framework services.\)#\1// added by post-processor\n\1services.AddTransient<IDbService, DbService>();\n\n\1\2#'
echo "copy database service into source code try" echo "create directories for manually developed code"
cp DbService.cs output/src/$PACKAGE_NAME/Services mkdir output/src/$PACKAGE_NAME/Implementations
mkdir output/src/$PACKAGE_NAME/Services
echo "generate endpoint code from openapi.yaml" echo "copy database service into source code try"
python3.10 generate.py cp DbService.cs output/src/$PACKAGE_NAME/Services
echo "copy endpoint code into source code tree"
cp regular.cs output/src/$PACKAGE_NAME/Implementations
if [ -f regular.cs ]; then
echo "copy endpoint code into source code tree"
cp regular.cs output/src/$PACKAGE_NAME/Implementations
else
echo "implementation not available, forgot to run stage 1?"
fi
fi
if [ "$BUILD" = "1" ]; then if [ "$BUILD" = "1" ]; then
echo "build service" echo "build service"

View File

@ -34,26 +34,6 @@ paths:
# responses: # responses:
# 201: # 201:
# description: Your items has been inserted # description: Your items has been inserted
/pdb/v2/test1/{id}:
get:
tags: [ "Regular" ]
operationId: Regular.test1byid
summary: Returns one entry from table test1 by id
parameters:
- name: id
in: path
required: true
schema:
type: integer
responses:
200:
description: Here is your test1 item
content:
application/json:
schema:
$ref: "#/components/schemas/test1"
404:
description: No such test1 item available
/pdb/v2/test1/specificSelectName: /pdb/v2/test1/specificSelectName:
get: get:
tags: [ "Regular" ] tags: [ "Regular" ]
@ -63,7 +43,7 @@ paths:
STATEMENTBEGIN STATEMENTBEGIN
select txt select txt
from test1 from test1
where nr = ? where nr = @nr
STATEMENTEND STATEMENTEND
INPUTMAPPINGBEGIN INPUTMAPPINGBEGIN
nr = Nummer nr = Nummer
@ -76,12 +56,12 @@ paths:
dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo
dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem
ipsum dolor sit amet. ipsum dolor sit amet.
requestBody: parameters:
description: specificSelectNameType - name: nr
content: in: query
application/json: required: true
schema: schema:
$ref: "#/components/schemas/specificSelectNameType" type: integer
responses: responses:
200: 200:
description: Here are your test1 items description: Here are your test1 items
@ -108,14 +88,6 @@ components:
type: string type: string
nr: nr:
type: integer type: integer
specificSelectNameType:
description: Specific type to defintion select condition
type: object
required:
- nr
properties:
nr:
type: integer
specificResultType: specificResultType:
description: Specific result type to defintion select clause description: Specific result type to defintion select clause
type: object type: object

View File

@ -1,9 +1,12 @@
$GENERATED_CS_COMMENT $GENERATED_CS_COMMENT
\#pragma warning disable 1591
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Runtime.Serialization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Swashbuckle.AspNetCore.Annotations; using Swashbuckle.AspNetCore.Annotations;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
@ -16,6 +19,29 @@ using ${env['packagename']}.Services;
namespace ${env['packagename']}.Implementations namespace ${env['packagename']}.Implementations
{ {
#for $operation in $operations
#if $operation['paramInputTypes']
// $operation['func']
[DataContract]
public class ${operation['func']}InputType
{
#for $inputType in $operation['paramInputTypes']
// $inputType['in']
// $inputType['name']
// $inputType['required']
// $inputType['type']
#if $inputType['required']
[Required]
#end if
[DataMember(Name="$inputType['name']")]
public int $inputType['csName'] { get; set; }
#end for
}
#end if
#end for
/// <summary> /// <summary>
/// </summary> /// </summary>
public class RegularApiImplementation : RegularApiController public class RegularApiImplementation : RegularApiController
@ -31,22 +57,66 @@ namespace ${env['packagename']}.Implementations
/// <summary> /// <summary>
/// $operation['description'] /// $operation['description']
/// </summary> /// </summary>
public override async Task<IActionResult> ${operation['func']}( #slurp public override async Task<IActionResult> ${operation['func']}(#slurp
#if $operation['paramsInputTypes'] #if $operation['bodyInputType']
#set $sep = ""
#for $paramsInputType in $operation['paramsInputTypes']
$sep [FromRoute (Name = "$paramsInputType['name']")] #slurp
#if $paramsInputType['required']
[Required] #slurp
#end if
$paramsInputType['type'] $paramsInputType['name'] #slurp
#set $sep = ","
#end for
#elif $operation['bodyInputType']
[FromBody]$operation['bodyInputType']['csName'] $operation['bodyInputType']['apiName'] #slurp [FromBody]$operation['bodyInputType']['csName'] $operation['bodyInputType']['apiName'] #slurp
#end if #end if
#if $operation['paramInputTypes']
#set sep = ''
#for $inputType in $operation['paramInputTypes']
$sep#slurp
#if $inputType['in'] == 'query'
[FromQuery #slurp
#elif $inputType['in'] == 'path'
[FromPath #slurp
#else
#raise Exception('Invalid in for paramInput')
#end if
(Name = "$inputType['name']")]#slurp
#if $inputType['required']
[Required()]#slurp
#end if
$inputType['type'] $inputType['name']#slurp
#set sep = ', '
#end for
#end if
) { ) {
List<$operation['resultType']['csName']> res = await _dbService.JustDoSomething<$operation['resultType']['csName']>("Hello ${operation['func']}"); #if $operation['paramInputTypes']
${operation['func']}InputType paramInput = new ${operation['func']}InputType();
#for $inputType in $operation['paramInputTypes']
paramInput.$inputType['csName'] = $inputType['name'];
#end for
#end if
List<$operation['resultType']['csName']> res = await _dbService.ReadBySelect<#slurp
#if $operation['bodyInputType']
$operation['bodyInputType']['csName'], #slurp
#elif $operation['paramInputTypes']
${operation['func']}InputType, #slurp
#else
Object, #slurp
#end if
$operation['resultType']['csName']>("#slurp
#if not $operation['statement']
SELECT #slurp
#set $sep = ""
#for $property in $types[$operation['resultType']['apiName']]['properties']
$sep$property['sqlName'] #slurp
#set $sep = ","
#end for
FROM $types[$operation['resultType']['apiName']]['sqlName']#slurp
#else
$operation['statement']#slurp
#end if
", #slurp
#if $operation['bodyInputType']
$operation['bodyInputType']['apiName']#slurp
#elif $operation['paramInputTypes']
paramInput#slurp
#else
null#slurp
#end if
);
// Statement: // Statement:
#if not $operation['statement'] #if not $operation['statement']
@ -94,3 +164,4 @@ $paramsInputType['type'] $paramsInputType['name'] #slurp
} }
} }
\#pragma warning restore 1591