private CProtoMessageField FindProtoMessageField(CProtoMessage protoMessage, CProperty property) { foreach (var protoField in protoMessage.ProtoField) { if (protoField.DerivedFrom is CColumn) { var column = protoField.DerivedFrom as CColumn; if (column.ColumnName == property.PropertyName) { return(protoField); } } if (protoField.DerivedFrom is CStoredProcedureParameter) { var parameter = protoField.DerivedFrom as CStoredProcedureParameter; if (parameter.SourceColumn.ColumnName == property.PropertyName) { return(protoField); } } if (protoField.FieldName == property.PropertyName) { return(protoField); } } return(null); }
private static string InferTableName(CProtoMessage message) { var tableName = message.MessageName; tableName = tableName.ReplaceAtStart("GetAll", ""); tableName = tableName.ReplaceAtStart("Get", ""); tableName = tableName.ReplaceAtStart("Is", ""); tableName = tableName.ReplaceAtStart("List", ""); tableName = tableName.ReplaceAtStart("Add", ""); tableName = tableName.ReplaceAtStart("Save", ""); tableName = tableName.ReplaceAtStart("Approve", ""); tableName = tableName.Replace("Find", ""); tableName = tableName.Replace("Check", ""); tableName = tableName.Replace("Read", ""); tableName = tableName.Replace("Create", ""); tableName = tableName.Replace("Queue", ""); tableName = tableName.Replace("Dequeue", ""); tableName = tableName.Replace("Delete", ""); tableName = tableName.Replace("Response", ""); tableName = tableName.Replace("Request", ""); var indexOfBy = tableName.IndexOf("By", StringComparison.CurrentCulture); if (indexOfBy > -1) { tableName = tableName.Substring(0, indexOfBy); } var s = new Inflector.Inflector(CultureInfo.CurrentCulture); tableName = s.Singularize(tableName); return(tableName); }
private void ProcessField(FieldDescriptor field, FileDescriptor descriptor, CProtoMessage protoMessage, List <CProtoMessage> messagesAdded) { bool processed = false; var messageType = GoogleGrpcTypeToGrpcType(field); if (MergeIfPossible) { if (messageType == GrpcType.__message && !field.IsRepeated) { //conservative merge: //merge the message into parent if it doesn't have any of its own child messages and its not a collection var childMessage = descriptor.MessageTypes.First(m => m.Name == field.MessageType.Name); var childFields = childMessage.Fields.InFieldNumberOrder().ToList(); if (childFields.All(f => GoogleGrpcTypeToGrpcType(f) != GrpcType.__message)) { foreach (var childField in childMessage.Fields.InFieldNumberOrder()) { protoMessage.ProtoField.Add(BuildProtoMessageField(childField)); } processed = true; messagesAdded.Add(new CProtoMessage(null) { MessageName = childMessage.Name }); } } } if (!processed) { protoMessage.ProtoField.Add(BuildProtoMessageField(field)); } }
private void InferTableType(IList <CTableType> tableTypes, CProtoRpc rpc, CProtoMessage messageIn) { var tableType = new CTableType(DataStoreTypes.SqlServer); tableType.Schema = InferSchema(rpc.ProtoService); tableType.TableName = "tt" + InferTableName(messageIn); tableType.DerivedFrom = messageIn; //add PK tableType.Column.Add(new CColumn(tableType) { ColumnName = $"{tableType.TableName}Id", IsNullable = false, ColumnTypeRaw = "bigint", ColumnType = System.Data.DbType.Int64, IsPrimaryKey = true, IsIdentity = false }); foreach (var p in messageIn.ProtoField) { var parameter = p; if (parameter.FieldType == GrpcType.__message) { //if the inner message is just a single scalar field, lets use that var m = rpc.ProtoService.ProtoFile.ProtoMessage.FirstOrDefault(pm => pm.MessageName == parameter.MessageType); if (m.ProtoField.Count == 1 && !parameter.Repeated) { parameter = m.ProtoField.First(); } else if (m.ProtoField.Count > 1) { continue; } else { continue; } } var columns = InferColumns(tableType, rpc, parameter); foreach (var col in columns) { if (!tableType.ColumnExists(col)) { tableType.Column.Add(col); } } } var existingTable = tableTypes.FirstOrDefault(t => t.TableName == tableType.TableName); if (existingTable != null) { //merge the tableTypes foreach (var col in tableType.Column) { if (!existingTable.ColumnExists(col)) { existingTable.Column.Add(col); } } } else { tableTypes.Add(tableType); } //now that tables has been added, add children //this will attempt to make sure they are in correct order for FK constraints foreach (var p in messageIn.ProtoField) { if (p.FieldType == GrpcType.__message && p.Repeated) { //if the inner message is just a single scalar field, lets use that var m = rpc.ProtoService.ProtoFile.ProtoMessage.FirstOrDefault(pm => pm.MessageName == p.MessageType); // if (m.ProtoField.Count > 1) //its repeated, so field count doesn't matter { //recurse InferTableType(tableTypes, rpc, m); } } } }
public CProtoFile Convert(List <CStoredProcedure> storedProcedures, bool addCRUD = false, bool addBulkRpc = true) { var protoFile = new CProtoFile(); protoFile.Import.Add("google/protobuf/timestamp.proto"); protoFile.Import.Add("google/protobuf/descriptor.proto"); //protoFile.Import.Add("google/protobuf/duration.proto"); protoFile.CSharpNamespace = NamespaceName; protoFile.Option.Add($@"csharp_namespace = ""{NamespaceName}"";"); var messagesToAddToBulkRpc = new List <CProtoMessage>(); var protoService = new CProtoService(protoFile) { ServiceName = ServiceName }; protoFile.ProtoService.Add(protoService); foreach (var storedProcedure in storedProcedures) { if (!addCRUD) { if (storedProcedure.DataOperationIs.HasFlag(COperationIs.CRUD)) { continue; } } var rpc = new CProtoRpc(protoService) { RpcName = storedProcedure.StoredProcedureName, RpcDescription = storedProcedure.StoredProcedureDescription, //DomainModelName = storedProcedure.ResultSetName, DerivedFrom = storedProcedure }; rpc.Request = new CProtoMessage(rpc) { IsRequest = true, MessageName = $"{storedProcedure.StoredProcedureName}Request" }; rpc.Response = new CProtoMessage(rpc) { IsResponse = true, MessageName = $"{storedProcedure.StoredProcedureName}Response" }; var requestMessage = rpc.Request; if (!string.IsNullOrEmpty(storedProcedure.ParameterSetName)) { rpc.Request.ProtoField.Add(new CProtoMessageField(storedProcedure) { IsScalar = false, MessageType = storedProcedure.ParameterSetName, FieldName = storedProcedure.ParameterSetName }); requestMessage = new CProtoMessage(rpc) { IsRequest = true, MessageName = storedProcedure.ParameterSetName }; if (!protoFile.ProtoMessage.Exists(pm => pm.MessageName == requestMessage.MessageName)) { protoFile.ProtoMessage.Add(requestMessage); if (addBulkRpc) { messagesToAddToBulkRpc.Add(requestMessage); } } } foreach (var parameter in storedProcedure.Parameter) { var sqlType = SqlDbType.VarChar; if (!parameter.ParameterTypeIsUserDefined) { sqlType = SqlMapper.ParseValueAsSqlDbType(parameter.ParameterTypeRaw); } var field = new CProtoMessageField(parameter) { FieldName = parameter.ParameterName, //.SourceColumn.ColumnName, FieldType = SqlMapper.SqlDbTypeToGrpcType(sqlType) }; if (parameter.ParameterTypeIsUserDefined) { field.Repeated = true; } requestMessage.ProtoField.Add(field); } var responseMessage = rpc.Response; if (!string.IsNullOrEmpty(storedProcedure.ResultSetName)) { rpc.Response.ProtoField.Add(new CProtoMessageField(null) { IsScalar = false, Repeated = true, MessageType = storedProcedure.ResultSetName, FieldName = storedProcedure.ResultSetName }); responseMessage = new CProtoMessage(rpc) { IsResponse = true, MessageName = storedProcedure.ResultSetName }; if (!protoFile.ProtoMessage.Exists(pm => pm.MessageName == responseMessage.MessageName)) { protoFile.ProtoMessage.Add(responseMessage); } } foreach (var resultColumn in storedProcedure.ResultSet) { var field = new CProtoMessageField(resultColumn) { FieldName = resultColumn.ColumnName, FieldType = SqlMapper.SqlDbTypeToGrpcType(resultColumn.ColumnSqlDbType) }; responseMessage.ProtoField.Add(field); } protoService.Rpc.Add(rpc); } /* * if (addBulkRpc) * { * var rpc = new SProtoRpc(protoService) * { * RpcName = $"{BulkStoreRpcName}", * OperationIs = SOperationIs.Bulk | SOperationIs.Add | SOperationIs.Update * }; * * var request = new SProtoMessage * { * IsRequest = true, * MessageName = $"{rpc.RpcName}Request" * * }; * * rpc.Request = request; * foreach (var message in messagesToAddToBulkRpc) * { * request.ProtoField.Add(new SProtoMessageField (null) { IsScalar = false, Repeated = true, MessageType = message.MessageName, FieldName = $"{message.MessageName}" }); * } * * var response = new SProtoMessage * { * IsResponse = true, * MessageName = $"{rpc.RpcName}Response" * }; * rpc.Response = response; * * * protoService.Rpc.Add(rpc); * }*/ return(protoFile); }
private CProtoRpc BuildRpcFromStoredProc(CProtoFile protoFile, CProtoService protoService, CMethod method, CStoredProcedure storedProcedure) { var rpc = new CProtoRpc(protoService) { RpcName = storedProcedure.StoredProcedureName, RpcDescription = storedProcedure.StoredProcedureDescription, //DomainModelName = storedProcedure.ResultSetName, DerivedFrom = storedProcedure }; rpc.Request = new CProtoMessage(rpc) { IsRequest = true, MessageName = $"{storedProcedure.StoredProcedureName}Request" }; rpc.Response = new CProtoMessage(rpc) { IsResponse = true, MessageName = $"{storedProcedure.StoredProcedureName}Response" }; var requestMessage = rpc.Request; if (!string.IsNullOrEmpty(storedProcedure.ParameterSetName)) { rpc.Request.ProtoField.Add(new CProtoMessageField(storedProcedure) { IsScalar = false, MessageType = storedProcedure.ParameterSetName, FieldName = storedProcedure.ParameterSetName }); requestMessage = new CProtoMessage(rpc) { IsRequest = true, MessageName = storedProcedure.ParameterSetName }; if (!protoFile.ProtoMessage.Exists(pm => pm.MessageName == requestMessage.MessageName)) { protoFile.ProtoMessage.Add(requestMessage); } } foreach (var parameter in storedProcedure.Parameter) { var field = new CProtoMessageField(parameter) { FieldName = parameter.ParameterName //.SourceColumn.ColumnName, }; if (!parameter.ParameterTypeIsUserDefined) { var sqlType = SqlMapper.ParseValueAsSqlDbType(parameter.ParameterTypeRaw); field.FieldType = SqlMapper.SqlDbTypeToGrpcType(sqlType); } else { //todo: property handle user defined sql types (tables) //lookup table type //for now, use the data type of the first column, assumes single column table var tableType = FindTableType(parameter.ParameterTypeRaw); var converter = new CTableTypeToCClassConverter(); var @class = converter.Convert(tableType.GeneratedTableType); field.FieldType = GrpcType.__string; field.IsScalar = false; field.Repeated = true; field.MessageType = $@"{@class.ClassName}"; if (!protoFile.ProtoMessage.Exists(pm => pm.MessageName == field.MessageType)) { //create a message var tableTypeDerivedMessage = new CProtoMessage(rpc) { MessageName = field.MessageType }; foreach (var property in @class.Property) { var field2 = new CProtoMessageField(property) { FieldName = property.PropertyName, FieldType = SqlMapper.ClrTypeToGrpcType(SqlMapper.ClrTypeAliasToClrType(property.Type)) }; tableTypeDerivedMessage.ProtoField.Add(field2); } protoFile.ProtoMessage.Add(tableTypeDerivedMessage); } } requestMessage.ProtoField.Add(field); } var responseMessage = rpc.Response; if (!string.IsNullOrEmpty(storedProcedure.ResultSetName)) { rpc.Response.ProtoField.Add(new CProtoMessageField(null) { IsScalar = false, Repeated = true, MessageType = storedProcedure.ResultSetName, FieldName = storedProcedure.ResultSetName }); responseMessage = new CProtoMessage(rpc) { IsResponse = true, MessageName = storedProcedure.ResultSetName }; if (!protoFile.ProtoMessage.Exists(pm => pm.MessageName == responseMessage.MessageName)) { protoFile.ProtoMessage.Add(responseMessage); } } foreach (var resultColumn in storedProcedure.ResultSet) { var field = new CProtoMessageField(resultColumn) { FieldName = resultColumn.ColumnName, FieldType = SqlMapper.SqlDbTypeToGrpcType(resultColumn.ColumnSqlDbType) }; responseMessage.ProtoField.Add(field); } return(rpc); }
private CProtoRpc BuildBulkRpcFromStoredProcList(CProtoFile protoFile, CProtoService protoService, CMethod method, CStoredProcList storedProcedureList) { var rpc = new CProtoRpc(protoService) { RpcName = method.MethodName, //DomainModelName = "Junk", // storedProcedure.ResultSetName,, DerivedFrom = storedProcedureList }; rpc.Request = new CProtoMessage(rpc) { IsRequest = true, MessageName = $"{method.MethodName}Request" }; rpc.Response = new CProtoMessage(rpc) { IsResponse = true, MessageName = $"{method.MethodName}Response" }; var requestMessage = rpc.Request; foreach (var storedProcedure in storedProcedureList.List) { if (!string.IsNullOrEmpty(storedProcedure.ParameterSetName)) { rpc.Request.ProtoField.Add(new CProtoMessageField(storedProcedure) { IsScalar = false, MessageType = storedProcedure.ParameterSetName, FieldName = storedProcedure.ParameterSetName, Repeated = true }); requestMessage = new CProtoMessage(rpc) { IsRequest = true, MessageName = storedProcedure.ParameterSetName }; if (!protoFile.ProtoMessage.Exists(pm => pm.MessageName == requestMessage.MessageName)) { protoFile.ProtoMessage.Add(requestMessage); } } foreach (var parameter in storedProcedure.Parameter) { var sqlType = SqlDbType.VarChar; if (!parameter.ParameterTypeIsUserDefined) { sqlType = SqlMapper.ParseValueAsSqlDbType(parameter.ParameterTypeRaw); } var field = new CProtoMessageField(parameter) { FieldName = parameter.ParameterName, //.SourceColumn.ColumnName, FieldType = SqlMapper.SqlDbTypeToGrpcType(sqlType) }; if (parameter.ParameterTypeIsUserDefined) { field.Repeated = true; } requestMessage.ProtoField.Add(field); } /* * var responseMessage = rpc.Response; * if (!string.IsNullOrEmpty(storedProcedure.ResultSetName)) * { * rpc.Response.ProtoField.Add(new SProtoMessageField(null) * { * IsScalar = false, * Repeated = true, * MessageType = storedProcedure.ResultSetName, * FieldName = storedProcedure.ResultSetName * }); * * responseMessage = new SProtoMessage * { * IsResponse = true, * MessageName = storedProcedure.ResultSetName * }; * if (!protoFile.ProtoMessage.Exists(pm => pm.MessageName == responseMessage.MessageName)) * { * protoFile.ProtoMessage.Add(responseMessage); * * } * * } * foreach (var resultColumn in storedProcedure.ResultSet) * { * var field = new SProtoMessageField(resultColumn) * { * FieldName = resultColumn.ColumnName, * FieldType = SqlMapper.SqlDbTypeToGrpcType(resultColumn.ColumnSqlDbType) * }; * * responseMessage.ProtoField.Add(field); * }*/ } return(rpc); }
public KProtoFile Convert(string protoFileName, string protoFileContent) { //1. save file to temp folder //2. run protoc compiler, convert to C# class //3. Compile the code in memory //4. Read the .Descriptor //5. Converto SProtoFile var codePath = GenerateCodeFromProto(protoFileContent); var code = GetGeneratedCode(codePath); var assembly = CompileCodeToAssembly(code); var descriptors = GetFileDescriptorsFromAssembly(assembly); var messagesAdded = new List <CProtoMessage>(); var protoFile = new CProtoFile(); protoFile.SourceProtoText = protoFileContent; foreach (var descriptorPair in descriptors) { var descriptor = descriptorPair.Value; protoFile.CSharpNamespace = descriptorPair.Key; protoFile.Import.Add("google/protobuf/timestamp.proto"); protoFile.Import.Add("google/protobuf/duration.proto"); protoFile.Import.Add("google/protobuf/descriptor.proto"); protoFile.Option.Add($@"csharp_namespace = ""{protoFile.CSharpNamespace}"";"); protoFile.Option.Add($@"(version) = ""1.0.0"";"); foreach (var service in descriptor.Services) { var protoService = new CProtoService(protoFile) { ServiceName = service.Name }; foreach (var method in service.Methods) { var protoServiceMethod = new CProtoRpc(protoService) { RpcName = method.Name }; protoService.Rpc.Add(protoServiceMethod); protoServiceMethod.Request = new CProtoMessage(protoServiceMethod) { MessageName = method.InputType.Name }; messagesAdded.Add(protoServiceMethod.Request); foreach (var field in method.InputType.Fields.InFieldNumberOrder()) { //protoServiceMethod.Request.ProtoField.Add(BuildProtoMessageField(field)); ProcessField(field, descriptor, protoServiceMethod.Request, messagesAdded); } protoServiceMethod.Response = new CProtoMessage(protoServiceMethod) { MessageName = method.OutputType.Name }; messagesAdded.Add(protoServiceMethod.Response); foreach (var field in method.OutputType.Fields.InFieldNumberOrder()) { //protoServiceMethod.Response.ProtoField.Add(BuildProtoMessageField(field)); ProcessField(field, descriptor, protoServiceMethod.Response, messagesAdded); } } protoFile.ProtoService.Add(protoService); } foreach (var enumType in descriptor.EnumTypes) { if (protoFile.ProtoEnum.Exists(pe => pe.EnumName == enumType.Name)) { continue; } var protoEnum = new CProtoEnum { EnumName = enumType.Name }; foreach (var enumTypeItem in enumType.Values) { var enumValue = new CProtoEnumValue { EnumValueName = enumTypeItem.Name, EnumValueNumber = enumTypeItem.Number }; protoEnum.EnumValue.Add(enumValue); } protoFile.ProtoEnum.Add(protoEnum); } foreach (var message in descriptor.MessageTypes) { if (messagesAdded.Exists(pm => pm.MessageName == message.Name)) { continue; } var protoMessage = new CProtoMessage(null) { MessageName = message.Name }; foreach (var field in message.Fields.InFieldNumberOrder()) { ProcessField(field, descriptor, protoMessage, messagesAdded); } protoFile.ProtoMessage.Add(protoMessage); messagesAdded.Add(protoMessage); } foreach (var dependency in descriptor.Dependencies) { foreach (var message in dependency.MessageTypes) { if (messagesAdded.Exists(pm => pm.MessageName == message.Name)) { continue; } var protoMessage = new CProtoMessage(null) { MessageName = message.Name, IsExternal = true }; protoFile.ProtoMessage.Add(protoMessage); messagesAdded.Add(protoMessage); } } } return(new KProtoFile { ProtoFileFile = protoFileName, GeneratedProtoFile = protoFile }); }