Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
edcade8
Changes for autoentities
RubenCerna2079 Jan 22, 2026
c380bb6
Add query and its execution
RubenCerna2079 Jan 26, 2026
aacecaa
Add testing
RubenCerna2079 Jan 27, 2026
d8b9856
Changes based on comments
RubenCerna2079 Jan 29, 2026
a8dfa5b
Changes based on comments
RubenCerna2079 Jan 29, 2026
35d335f
Added changes based on comments
RubenCerna2079 Jan 30, 2026
5cf3424
Fix formatting issues
RubenCerna2079 Jan 30, 2026
4dd7c0e
Generate in-memory entities
RubenCerna2079 Feb 5, 2026
687c6c8
Changes to generate autoentities as entities
RubenCerna2079 Feb 11, 2026
f44e5ab
Add new testing
RubenCerna2079 Feb 12, 2026
ce3bb09
Fix grammar errors
RubenCerna2079 Feb 13, 2026
bcd0a52
Changes to ensure autoentities work with multiple data sources
RubenCerna2079 Feb 20, 2026
b0b426e
Move validation of entities
RubenCerna2079 Feb 21, 2026
923a7af
Change test
RubenCerna2079 Feb 21, 2026
e521b08
Add testing
RubenCerna2079 Feb 21, 2026
bbf5ceb
Refactor code
RubenCerna2079 Feb 23, 2026
9e62a65
Fix Tests
RubenCerna2079 Feb 25, 2026
18c90d8
Fix syntax errors
RubenCerna2079 Feb 26, 2026
ef3c23e
Changes based on comments
RubenCerna2079 Feb 26, 2026
9d30fd9
Fix test errors by replacing mock with real object
RubenCerna2079 Feb 27, 2026
f8435ae
Fix test syntax
RubenCerna2079 Feb 27, 2026
f27293e
Fix syntax
RubenCerna2079 Feb 27, 2026
77f0803
Fix tests
RubenCerna2079 Feb 27, 2026
b50069e
Changes based on comment
RubenCerna2079 Feb 28, 2026
974b455
Merge branch 'main' into dev/rubencerna/update-validation-autoentities
RubenCerna2079 Feb 28, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 39 additions & 12 deletions src/Core/Configurations/RuntimeConfigValidator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -96,18 +96,6 @@ public void ValidateConfigProperties()
ValidateLoggerFilters(runtimeConfig);
ValidateAzureLogAnalyticsAuth(runtimeConfig);
ValidateFileSinkPath(runtimeConfig);

// Running these graphQL validations only in development mode to ensure
// fast startup of engine in production mode.
if (runtimeConfig.IsDevelopmentMode())
{
ValidateEntityConfiguration(runtimeConfig);

if (runtimeConfig.IsGraphQLEnabled)
{
ValidateEntitiesDoNotGenerateDuplicateQueriesOrMutation(runtimeConfig.DataSource.DatabaseType, runtimeConfig.Entities);
}
}
}

/// <summary>
Expand Down Expand Up @@ -330,6 +318,19 @@ public async Task<bool> TryValidateConfig(

JsonSchemaValidationResult validationResult = await ValidateConfigSchema(runtimeConfig, configFilePath, loggerFactory);
ValidateConfigProperties();

// Running these graphQL validations only in development mode to ensureExpand commentComment on line L100
// fast startup of engine in production mode.
if (runtimeConfig.IsDevelopmentMode())
{
ValidateEntityConfiguration(runtimeConfig);

if (runtimeConfig.IsGraphQLEnabled)
{
ValidateEntitiesDoNotGenerateDuplicateQueriesOrMutation(runtimeConfig.DataSource.DatabaseType, runtimeConfig.Entities);
}
}

ValidatePermissionsInConfig(runtimeConfig);

_logger.LogInformation("Validating entity relationships.");
Expand Down Expand Up @@ -499,6 +500,7 @@ public async Task ValidateEntitiesMetadata(RuntimeConfig runtimeConfig, ILoggerF
// Only used for validation so we don't need the handler which is for hot reload scenarios.
MetadataProviderFactory metadataProviderFactory = new(
runtimeConfigProvider: _runtimeConfigProvider,
runtimeConfigValidator: this,
queryManagerFactory: queryManagerFactory,
logger: loggerFactory.CreateLogger<ISqlMetadataProvider>(),
fileSystem: _fileSystem,
Expand Down Expand Up @@ -1594,4 +1596,29 @@ private static bool IsLoggerFilterValid(string loggerFilter)

return false;
}

/// <summary>
/// Checks that all of the entities created with the Entities and Autoentities properties
/// are valid by having unique paths for both REST and GraphQL, that there are no duplicate
/// Queries or Mutation entities, and ensure the semantic correctness of all the entities.
/// </summary>
/// <param name="runtimeConfig">The runtime configuration.</param>
public async Task ValidateEntityAndAutoentityConfigurations(RuntimeConfig runtimeConfig)
{
if (runtimeConfig.IsDevelopmentMode())
{
ValidateEntityConfiguration(runtimeConfig);

if (runtimeConfig.IsGraphQLEnabled)
{
ValidateEntitiesDoNotGenerateDuplicateQueriesOrMutation(runtimeConfig.DataSource.DatabaseType, runtimeConfig.Entities);
}

// Running only in developer mode to ensure fast and smooth startup in production.
ValidatePermissionsInConfig(runtimeConfig);
}

ILoggerFactory loggerFactory = new LoggerFactory();
await ValidateEntitiesMetadata(runtimeConfig, loggerFactory);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public class CosmosSqlMetadataProvider : ISqlMetadataProvider

public List<Exception> SqlMetadataExceptions { get; private set; } = new();

public CosmosSqlMetadataProvider(RuntimeConfigProvider runtimeConfigProvider, IFileSystem fileSystem)
public CosmosSqlMetadataProvider(RuntimeConfigProvider runtimeConfigProvider, RuntimeConfigValidator runtimeConfigValidator, IFileSystem fileSystem)
{
RuntimeConfig runtimeConfig = runtimeConfigProvider.GetConfig();
_fileSystem = fileSystem;
Expand Down
13 changes: 8 additions & 5 deletions src/Core/Services/MetadataProviders/MetadataProviderFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,15 @@ public class MetadataProviderFactory : IMetadataProviderFactory
{
private readonly IDictionary<string, ISqlMetadataProvider> _metadataProviders;
private readonly RuntimeConfigProvider _runtimeConfigProvider;
private readonly RuntimeConfigValidator _runtimeConfigValidator;
private readonly IAbstractQueryManagerFactory _queryManagerFactory;
private readonly ILogger<ISqlMetadataProvider> _logger;
private readonly IFileSystem _fileSystem;
private readonly bool _isValidateOnly;

public MetadataProviderFactory(
RuntimeConfigProvider runtimeConfigProvider,
RuntimeConfigValidator runtimeConfigValidator,
IAbstractQueryManagerFactory queryManagerFactory,
ILogger<ISqlMetadataProvider> logger,
IFileSystem fileSystem,
Expand All @@ -34,6 +36,7 @@ public MetadataProviderFactory(
{
handler?.Subscribe(METADATA_PROVIDER_FACTORY_ON_CONFIG_CHANGED, OnConfigChanged);
_runtimeConfigProvider = runtimeConfigProvider;
_runtimeConfigValidator = runtimeConfigValidator;
_queryManagerFactory = queryManagerFactory;
_logger = logger;
_fileSystem = fileSystem;
Expand All @@ -48,11 +51,11 @@ private void ConfigureMetadataProviders()
{
ISqlMetadataProvider metadataProvider = dataSource.DatabaseType switch
{
DatabaseType.CosmosDB_NoSQL => new CosmosSqlMetadataProvider(_runtimeConfigProvider, _fileSystem),
DatabaseType.MSSQL => new MsSqlMetadataProvider(_runtimeConfigProvider, _queryManagerFactory, _logger, dataSourceName, _isValidateOnly),
DatabaseType.DWSQL => new MsSqlMetadataProvider(_runtimeConfigProvider, _queryManagerFactory, _logger, dataSourceName, _isValidateOnly),
DatabaseType.PostgreSQL => new PostgreSqlMetadataProvider(_runtimeConfigProvider, _queryManagerFactory, _logger, dataSourceName, _isValidateOnly),
DatabaseType.MySQL => new MySqlMetadataProvider(_runtimeConfigProvider, _queryManagerFactory, _logger, dataSourceName, _isValidateOnly),
DatabaseType.CosmosDB_NoSQL => new CosmosSqlMetadataProvider(_runtimeConfigProvider, _runtimeConfigValidator, _fileSystem),
DatabaseType.MSSQL => new MsSqlMetadataProvider(_runtimeConfigProvider, _runtimeConfigValidator, _queryManagerFactory, _logger, dataSourceName, _isValidateOnly),
DatabaseType.DWSQL => new MsSqlMetadataProvider(_runtimeConfigProvider, _runtimeConfigValidator, _queryManagerFactory, _logger, dataSourceName, _isValidateOnly),
DatabaseType.PostgreSQL => new PostgreSqlMetadataProvider(_runtimeConfigProvider, _runtimeConfigValidator, _queryManagerFactory, _logger, dataSourceName, _isValidateOnly),
DatabaseType.MySQL => new MySqlMetadataProvider(_runtimeConfigProvider, _runtimeConfigValidator, _queryManagerFactory, _logger, dataSourceName, _isValidateOnly),
_ => throw new NotSupportedException(dataSource.DatabaseTypeNotSupportedMessage),
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,12 @@ public class MsSqlMetadataProvider :

public MsSqlMetadataProvider(
RuntimeConfigProvider runtimeConfigProvider,
RuntimeConfigValidator runtimeConfigValidator,
IAbstractQueryManagerFactory queryManagerFactory,
ILogger<ISqlMetadataProvider> logger,
string dataSourceName,
bool isValidateOnly = false)
: base(runtimeConfigProvider, queryManagerFactory, logger, dataSourceName, isValidateOnly)
: base(runtimeConfigProvider, runtimeConfigValidator, queryManagerFactory, logger, dataSourceName, isValidateOnly)
{
_runtimeConfigProvider = runtimeConfigProvider;
}
Expand Down Expand Up @@ -374,7 +375,7 @@ protected override async Task GenerateAutoentitiesIntoEntities(IReadOnlyDictiona

if (addedEntities == 0)
{
_logger.LogWarning($"No new entities were generated from the autoentity {autoentityName} defined in the configuration.");
_logger.LogWarning("No new entities were generated from the autoentity {autoentityName} defined in the configuration.", autoentityName);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,12 @@ public class MySqlMetadataProvider : SqlMetadataProvider<MySqlConnection, MySqlD

public MySqlMetadataProvider(
RuntimeConfigProvider runtimeConfigProvider,
RuntimeConfigValidator runtimeConfigValidator,
IAbstractQueryManagerFactory queryManagerFactory,
ILogger<ISqlMetadataProvider> logger,
string dataSourceName,
bool isValidateOnly = false)
: base(runtimeConfigProvider, queryManagerFactory, logger, dataSourceName, isValidateOnly)
: base(runtimeConfigProvider, runtimeConfigValidator, queryManagerFactory, logger, dataSourceName, isValidateOnly)
{
try
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,12 @@ public class PostgreSqlMetadataProvider :

public PostgreSqlMetadataProvider(
RuntimeConfigProvider runtimeConfigProvider,
RuntimeConfigValidator runtimeConfigValidator,
IAbstractQueryManagerFactory queryManagerFactory,
ILogger<ISqlMetadataProvider> logger,
string dataSourceName,
bool isValidateOnly = false)
: base(runtimeConfigProvider, queryManagerFactory, logger, dataSourceName, isValidateOnly)
: base(runtimeConfigProvider, runtimeConfigValidator, queryManagerFactory, logger, dataSourceName, isValidateOnly)
{
}

Expand Down
21 changes: 16 additions & 5 deletions src/Core/Services/MetadataProviders/SqlMetadataProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ public abstract class SqlMetadataProvider<ConnectionT, DataAdapterT, CommandT> :

private RuntimeConfigProvider _runtimeConfigProvider;

private RuntimeConfigValidator _runtimeConfigValidator;

private Dictionary<string, Dictionary<string, string>> EntityBackingColumnsToExposedNames { get; } = new();

private Dictionary<string, Dictionary<string, string>> EntityExposedNamesToBackingColumnNames { get; } = new();
Expand Down Expand Up @@ -108,13 +110,15 @@ private void HandleOrRecordException(Exception e)

public SqlMetadataProvider(
RuntimeConfigProvider runtimeConfigProvider,
RuntimeConfigValidator runtimeConfigValidator,
IAbstractQueryManagerFactory engineFactory,
ILogger<ISqlMetadataProvider> logger,
string dataSourceName,
bool isValidateOnly = false)
{
RuntimeConfig runtimeConfig = runtimeConfigProvider.GetConfig();
_runtimeConfigProvider = runtimeConfigProvider;
_runtimeConfigValidator = runtimeConfigValidator;
_dataSourceName = dataSourceName;
_databaseType = runtimeConfig.GetDataSourceFromDataSourceName(dataSourceName).DatabaseType;
_logger = logger;
Expand Down Expand Up @@ -310,12 +314,7 @@ public string GetEntityName(string graphQLType)
public async Task InitializeAsync()
{
System.Diagnostics.Stopwatch timer = System.Diagnostics.Stopwatch.StartNew();
if (GetDatabaseType() == DatabaseType.MSSQL)
{
await GenerateAutoentitiesIntoEntities(Autoentities);
}

GenerateDatabaseObjectForEntities();
if (_isValidateOnly)
{
// Currently Validate mode only support single datasource,
Expand All @@ -332,6 +331,18 @@ public async Task InitializeAsync()
}
}

if (GetDatabaseType() == DatabaseType.MSSQL)
{
await GenerateAutoentitiesIntoEntities(Autoentities);
}

// Running these graphQL validations only in development mode to ensure
// fast startup of engine in production mode.
RuntimeConfig runtimeConfig = _runtimeConfigProvider.GetConfig();
await _runtimeConfigValidator.ValidateEntityAndAutoentityConfigurations(runtimeConfig);

GenerateDatabaseObjectForEntities();

await PopulateObjectDefinitionForEntities();
GenerateExposedToBackingColumnMapsForEntities();
// When IsLateConfigured is true we are in a hosted scenario and do not reveal primary key information.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.IO.Abstractions;
using System.Net;
using System.Reflection;
using System.Text.Json;
Expand Down Expand Up @@ -699,10 +700,14 @@ private static Mock<SqlQueryStructure> CreateMockSqlQueryStructure(string entity
entityToDatabaseObject.Add(entityName, new DatabaseTable());

Mock<RuntimeConfigProvider> mockRuntimeConfigProvider = CreateMockRuntimeConfigProvider(entityName);
IFileSystem fileSystem = new FileSystem();
Mock<ILogger<RuntimeConfigValidator>> loggerValidator = new();
RuntimeConfigValidator runtimeConfigValidator = new(mockRuntimeConfigProvider.Object, fileSystem, loggerValidator.Object);
Mock<IAbstractQueryManagerFactory> mockQueryFactory = new();
Mock<ILogger<ISqlMetadataProvider>> mockLogger = new();
Mock<MsSqlMetadataProvider> mockSqlMetadataProvider = new(
mockRuntimeConfigProvider.Object,
runtimeConfigValidator,
mockQueryFactory.Object,
mockLogger.Object,
dataSourceName,
Expand Down
Loading
Loading