private void InferTable(IList <CTable> tables, CProtoRpc rpc, CProtoMessage messageIn, CTable parentTable) { var table = new CTable(DataStoreTypes.SqlServer); table.Schema = InferSchema(rpc.ProtoService); table.TableName = InferTableName(messageIn); table.DerivedFrom = messageIn; //add PK, Identity table.Column.Add(new CColumn(table) { ColumnName = $"{table.TableName}Id", IsNullable = false, ColumnTypeRaw = "bigint", ColumnType = System.Data.DbType.Int64, IsPrimaryKey = true, IsIdentity = true }); if (parentTable != null) { var fk = parentTable.Column.FirstOrDefault(c => c.IsPrimaryKey); if (fk != null) { var fkColumn = new CColumn(table) { ColumnName = fk.ColumnName, IsNullable = fk.IsNullable, ColumnType = fk.ColumnType, ColumnTypeRaw = fk.ColumnTypeRaw, IsIdentity = false }; fkColumn.ForeignKeyColumn.Add(fk); table.Column.Add(fkColumn); } } 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(table, rpc, parameter); foreach (var col in columns) { if (!table.ColumnExists(col)) { table.Column.Add(col); } } } var existingTable = tables.FirstOrDefault(t => t.TableName == table.TableName); if (existingTable != null) { //merge the tables foreach (var col in table.Column) { if (!existingTable.ColumnExists(col)) { existingTable.Column.Add(col); } } } else { tables.Add(table); } //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 InferTable(tables, rpc, m, table); } } } }