Skip to content

Create Entities in-memory from Autoentities#3129

Open
RubenCerna2079 wants to merge 15 commits intomainfrom
dev/rubencerna/create-inmemory-entities-from-autoentities
Open

Create Entities in-memory from Autoentities#3129
RubenCerna2079 wants to merge 15 commits intomainfrom
dev/rubencerna/create-inmemory-entities-from-autoentities

Conversation

@RubenCerna2079
Copy link
Contributor

@RubenCerna2079 RubenCerna2079 commented Feb 13, 2026

Why make this change?

  • Create entities in-memory from autoentities #3052
    We need to generate all the entities from the autoentities properties. In order to do this we need to use the query that was previously created and, add the newly generated entities into the runtime so the user can use them.

What is this change?

  • MsSqlMetadataProvider.cs: Finish creating the GenerateAutoentitiesIntoEntities function so that it uses the query to receive all of the tables and turn them into entities inside the runtimeConfig.
  • RuntimeConfig.cs: Create new function that adds the new entities to the runtimeConfig. And also change the runtimeConfig to allow for the entities property to be missing if the user decides to use the autoentities property.

How was this tested?

  • Integration Tests
  • Unit Tests

@RubenCerna2079 RubenCerna2079 added this to the Feb 2026 milestone Feb 13, 2026
@RubenCerna2079 RubenCerna2079 self-assigned this Feb 13, 2026
@RubenCerna2079 RubenCerna2079 linked an issue Feb 13, 2026 that may be closed by this pull request
@RubenCerna2079 RubenCerna2079 force-pushed the dev/rubencerna/create-inmemory-entities-from-autoentities branch from 1972a8f to 2f256e4 Compare February 13, 2026 00:52
@RubenCerna2079 RubenCerna2079 marked this pull request as ready for review February 13, 2026 01:13
Copilot AI review requested due to automatic review settings February 13, 2026 01:13
@RubenCerna2079
Copy link
Contributor Author

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 6 pipeline(s).

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR enables auto-generating entity definitions from autoentities at runtime (in-memory) so the generated entities become usable by the REST/GraphQL runtime without being serialized into the entities section of the config.

Changes:

  • Implemented MSSQL autoentity generation to materialize matching tables into RuntimeConfig.Entities during metadata initialization.
  • Updated RuntimeConfig/validation to allow entities to be omitted when autoentities is present, and added APIs to mutate the in-memory runtime config.
  • Added an MSSQL test covering autoentities generation with/without pre-existing entities.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 10 comments.

Show a summary per file
File Description
src/Service/Startup.cs Adds TODOs related to validation placement with autoentity generation.
src/Service.Tests/Configuration/ConfigurationTests.cs Adds test coverage for autoentities generating usable REST/GraphQL endpoints.
src/Core/Services/MetadataProviders/SqlMetadataProvider.cs Exposes _entities to derived classes and triggers autoentity generation during MSSQL initialization.
src/Core/Services/MetadataProviders/MsSqlMetadataProvider.cs Implements GenerateAutoentitiesIntoEntities() and query execution for autoentities.
src/Core/Configurations/RuntimeConfigValidator.cs Allows entity validation loop to safely handle missing Entities.
src/Core/Configurations/RuntimeConfigProvider.cs Adds method to replace runtime config entities in-memory after generation.
src/Config/RuntimeConfigLoader.cs Adds a setter-style method to update the active RuntimeConfig instance.
src/Config/ObjectModel/RuntimeConfig.cs Allows missing entities when autoentities exists; adds entity->datasource mapping helper.

Comment on lines +248 to +250
public bool TryAddEntityNameToDataSourceName(string entityName)
{
return _entityNameToDataSourceName.TryAdd(entityName, this.DefaultDataSourceName);
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method always maps newly added entities to DefaultDataSourceName. That will be incorrect when autoentities are generated while initializing a non-default datasource (multi-database scenario). Consider changing the API to accept a dataSourceName (and use _dataSourceName from the metadata provider) so the entity->datasource mapping stays correct.

Suggested change
public bool TryAddEntityNameToDataSourceName(string entityName)
{
return _entityNameToDataSourceName.TryAdd(entityName, this.DefaultDataSourceName);
public bool TryAddEntityNameToDataSourceName(string entityName, string? dataSourceName = null)
{
string effectiveDataSourceName = string.IsNullOrEmpty(dataSourceName) ? this.DefaultDataSourceName : dataSourceName;
return _entityNameToDataSourceName.TryAdd(entityName, effectiveDataSourceName);

Copilot uses AI. Check for mistakes.
Comment on lines +417 to +420
RuntimeConfig newRuntimeConfig = _configLoader.RuntimeConfig! with
{
Entities = new(entities)
};
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AddNewEntitiesToConfig replaces the entire RuntimeConfig.Entities collection with the provided dictionary. In multi-datasource scenarios (or any scenario where entities is a subset), this can unintentionally drop entities and desync internal lookup dictionaries. Prefer merging with the existing entity set (and updating the entity->datasource map consistently) rather than overwriting.

Suggested change
RuntimeConfig newRuntimeConfig = _configLoader.RuntimeConfig! with
{
Entities = new(entities)
};
// Merge incoming entities into the existing entity set instead of overwriting it.
RuntimeConfig currentRuntimeConfig = _configLoader.RuntimeConfig!;
Dictionary<string, Entity> mergedEntities = new(currentRuntimeConfig.Entities);
foreach ((string entityName, Entity entityDefinition) in entities)
{
// Add new entities or update existing ones with the provided definitions.
mergedEntities[entityName] = entityDefinition;
}
RuntimeConfig newRuntimeConfig = currentRuntimeConfig with
{
Entities = mergedEntities
};

Copilot uses AI. Check for mistakes.
Comment on lines +300 to +305
Dictionary<string, Entity> entities = (Dictionary<string, Entity>)_entities;
if (runtimeConfig.Autoentities is null)
{
return;
}

Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

entities is taken from _entities, which is a per-datasource filtered dictionary (see SqlMetadataProvider ctor). Passing that dictionary into AddNewEntitiesToConfig risks replacing RuntimeConfig.Entities with only the entities for this datasource, dropping entities for other datasources and leaving _entityNameToDataSourceName inconsistent. Use the full runtimeConfig.Entities.Entities as the base and merge in generated entities, or make AddNewEntitiesToConfig merge rather than replace.

Suggested change
Dictionary<string, Entity> entities = (Dictionary<string, Entity>)_entities;
if (runtimeConfig.Autoentities is null)
{
return;
}
if (runtimeConfig.Autoentities is null)
{
return;
}
// Start from the full set of entities defined in the runtime configuration,
// not the per-datasource filtered _entities dictionary, so that when we
// persist new auto-generated entities we don't drop entities for other datasources.
Dictionary<string, Entity> entities = new(runtimeConfig.Entities.Entities);

Copilot uses AI. Check for mistakes.
Comment on lines +318 to +335
string entityName = resultObject["entity_name"]!.ToString();
string schemaName = resultObject["schema"]!.ToString();
string objectName = resultObject["object"]!.ToString();

if (string.IsNullOrWhiteSpace(entityName) || string.IsNullOrWhiteSpace(objectName))
{
_logger.LogError("Skipping autoentity generation: entity_name or object is null or empty for autoentity pattern '{AutoentityName}'.", autoentityName);
continue;
}

// Create the entity using the template settings and permissions from the autoentity configuration.
// Currently the source type is always Table for auto-generated entities from database objects.
Entity generatedEntity = new(
Source: new EntitySource(
Object: objectName,
Type: EntitySourceType.Table,
Parameters: null,
KeyFields: null),
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

schemaName is read from the autoentities query but not used. If a matched table is in a non-default schema, setting EntitySource.Object to just objectName will make DAB resolve it against the default schema (dbo) and point to the wrong table. Consider using a schema-qualified source (e.g., schemaName.objectName) when schemaName is not empty/default.

Copilot uses AI. Check for mistakes.
using (HttpClient client = server.CreateClient())
{
// Act
HttpRequestMessage restRequest = new(HttpMethod.Get, "/api/publishers");
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Disposable 'HttpRequestMessage' is created but not disposed.

Copilot uses AI. Check for mistakes.
Comment on lines +5351 to +5354
HttpRequestMessage graphqlRequest = new(HttpMethod.Post, "/graphql")
{
Content = JsonContent.Create(graphqlPayload)
};
Copy link

Copilot AI Feb 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Disposable 'HttpRequestMessage' is created but not disposed.

Copilot uses AI. Check for mistakes.
@RubenCerna2079
Copy link
Contributor Author

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 6 pipeline(s).

{
throw new DataApiBuilderException(
message: "entities is a mandatory property in DAB Config",
message: "Configuration file should contain either at least the Entities or Autoentities property",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
message: "Configuration file should contain either at least the Entities or Autoentities property",
message: "Configuration file should contain either at least the entities or autoentities property",

}
else
{
_runtimeConfigProvider.AddNewEntitiesToConfig(entities);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dont we have access to the RuntimeConfigLoader here?

return runtimeConfig;
}

public void AddNewEntitiesToConfig(Dictionary<string, Entity> entities)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change the function name to "AddMergedEntitiesToConfig" since the entities passed in here, are all the entities - original + entities found from autoentities.


string[] args = new[] { $"--ConfigFileName={CUSTOM_CONFIG_FILENAME}" };

using (TestServer server = new(Program.CreateWebHostBuilder(args)))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you also retrieve the serviceProvider -> RuntimeConfigProvider and the RuntimeConfig to check the entities member has 3 entities with useentity and 1 when not using previous entities?

@RubenCerna2079
Copy link
Contributor Author

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 6 pipeline(s).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

Status: Todo

Development

Successfully merging this pull request may close these issues.

Create entities in-memory from autoentities

2 participants