Skip to content

Improve GraphQL naming conflict error to identify conflicting entities and operations - #3722

Open
RubenCerna2079 with Copilot wants to merge 9 commits into
mainfrom
copilot/fix-duplicate-graphql-operations
Open

Improve GraphQL naming conflict error to identify conflicting entities and operations#3722
RubenCerna2079 with Copilot wants to merge 9 commits into
mainfrom
copilot/fix-duplicate-graphql-operations

Conversation

Copilot AI commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Why make this change?

When autoentities includes tables whose names differ only by singular/plural form (e.g. dbo.Category and dbo.Categories), DAB fails startup with a vague error that doesn't identify the other conflicting entity, the generated GraphQL names, or how to resolve the conflict.

What is this change?

  • RuntimeConfigValidator.ValidateEntitiesDoNotGenerateDuplicateQueriesOrMutation: Replaced HashSet<string> operation tracking with Dictionary<string, string> (operation → owning entity). Checks all operations (not short-circuit) to collect every conflicting name, then builds a structured error message including:
    • Both conflicting entity names
    • Singular/plural type names (for table/view entities)

Before:

Entity dbo_Category generates queries/mutation that already exist

After:

GraphQL naming conflict detected.

Entities:
  dbo_Categories
  dbo_Category

Both entities generate the following GraphQL names:
  Singular type: Category
  Plural type: Categories

Configure distinct GraphQL singular and plural names for one of the entities to resolve this conflict.

How was this tested?

  • Integration Tests
  • Unit Tests
    • Updated ValidateExceptionForDuplicateQueriesDueToEntityDefinitions helper to verify both conflicting entity names appear in the message
    • Updated all 6 existing duplicate-detection test call sites
    • Added ValidateAutoEntitiesWithSingularPluralNameCollisionGenerateDuplicateQueries covering the exact dbo.Category / dbo.Categories scenario

Sample Request(s)

N/A — error message improvement only; no API behavior changes.

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
There may be pipelines that require an authorized user to comment /azp run to run.

Copilot AI changed the title [WIP] Fix autoentities conflict with duplicate GraphQL operations Improve GraphQL naming conflict error to identify conflicting entities and operations Jul 14, 2026
Copilot AI requested a review from RubenCerna2079 July 14, 2026 21:25
@RubenCerna2079

Copy link
Copy Markdown
Contributor

@copilot Change the PR so that in the output message we don't include the operation names. Also, if possible we want to keep using the hashset we already used before. Try to change the logic as little as possible from what it was before the changes you made in this PR. The only change should be the error message.

Copilot AI commented Jul 22, 2026

Copy link
Copy Markdown
Contributor Author

Copilot Change the PR so that in the output message we don't include the operation names. Also, if possible we want to keep using the hashset we already used before. Try to change the logic as little...

Done in 3a1f2d0. The changes are now minimal:

  • Reverted back to HashSet<string> with the original bool containsDuplicateOperationNames flag and || short-circuit chain
  • Added a parallel Dictionary<string, string> operationOwner (only used for error reporting) to identify which entity previously registered the conflicting operations
  • The error message now shows both conflicting entity names but no operation names

New message format:

GraphQL naming conflict detected.

Entities:
  dbo_Categories
  dbo_Category

Configure distinct GraphQL singular and plural names for one of the entities to resolve this conflict.

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
There may be pipelines that require an authorized user to comment /azp run to run.

@RubenCerna2079

Copy link
Copy Markdown
Contributor

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 6 pipeline(s).

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Improves configuration-time GraphQL naming conflict diagnostics by augmenting RuntimeConfigValidator.ValidateEntitiesDoNotGenerateDuplicateQueriesOrMutation to track which entity “owns” each generated GraphQL operation name and by updating unit tests to validate the richer error output (including a new unit test for singular/plural auto-entity collisions).

Changes:

  • Enhanced duplicate GraphQL operation detection to retain the owning entity per operation and emit a more structured conflict message.
  • Updated existing unit tests to assert the new message shape (prefix + both entity names).
  • Added a unit test covering dbo.Category vs dbo.Categories (singular/plural collision) behavior.

Reviewed changes

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

File Description
src/Core/Configurations/RuntimeConfigValidator.cs Tracks operation ownership and builds a more detailed GraphQL naming conflict exception message.
src/Service.Tests/UnitTests/ConfigValidationUnitTests.cs Updates duplicate-detection assertions and adds a new unit test for singular/plural auto-entity collisions.

Comment on lines +973 to 985
else
{
operationOwner[pkQueryName] = entityName;
operationOwner[listQueryName] = entityName;
operationOwner[createMutationName] = entityName;
operationOwner[updateMutationName] = entityName;
operationOwner[deleteMutationName] = entityName;
if (databaseType is DatabaseType.CosmosDB_NoSQL)
{
operationOwner[patchMutationName] = entityName;
}
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

That should not be possible since the if statement that is used previously to this already checks all the possible operationOwners with the name

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Validate only mode can lose operation ownership after an earlier conflict. The || chain mutates graphQLOperationNames incrementally, but operationOwner is populated only in the else block after every Add succeeds.

If an earlier Add succeeds and a later Add fails, the successfully added operation remains in graphQLOperationNames without an owner. Because validate-only mode continues processing, a later entity can collide with that operation and the resulting message omits the actual conflicting entity.

You can repro this with First (Alpha/Shared), Second (Beta/Shared), and Third (Beta/Thirds). Second successfully adds beta_by_pk before failing on Shared, but beta_by_pk is never assigned an owner. Third then conflicts on beta_by_pk, and its recorded error lists only Third instead of identifying Second.

I think we should record ownership immediately for each successful Add, or possibly use the operation-to-owner dictionary as the authoritative duplicate check.

A validate-only regression test should cover this sequence.

Comment thread src/Core/Configurations/RuntimeConfigValidator.cs
@RubenCerna2079

Copy link
Copy Markdown
Contributor

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 6 pipeline(s).

@RubenCerna2079

Copy link
Copy Markdown
Contributor

/azp run

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 6 pipeline(s).


if (containsDuplicateOperationNames)
{
string entitiesStr = string.IsNullOrEmpty(conflictingEntityName)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The new message can report non-conflicting names as shared. entityNamesStr always contains the current entity's singular and plural names, but the message labels both values as names generated by both entities regardless of which operation actually collided.

Isn't this incorrect for singular-only and plural-only conflicts, where the other configured name can be different? Likewise for stored-procedure/table conflicts, where the generated operation fields can collide even though the entities singular and plural type names differ.

I'm thinking we should probably track and display only the generated names that actually conflict, and if the implementation can not retain that information, this section should be removed or reworded so it does not claim both entities generate both displayed names.

|| ((databaseType is DatabaseType.CosmosDB_NoSQL) && !graphQLOperationNames.Add(patchMutationName)))
{
containsDuplicateOperationNames = true;
conflictingEntityName =

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This lookup reports only the first conflicting owner, but one entity can conflict with different prior entities on different generated names.

For example, if A uses Alpha/Shared, B uses Beta/Betas, and C uses Beta/Shared, C conflicts with B through its singular-derived operations and with A through its plural list query. The current null-coalescing chain reports only B and omits A, so the user may fix the reported conflict only to encounter another startup failure for the same entity.

Could we collect all distinct owners of the conflicting generated names and include every conflicting entity in the diagnostic instead?

@aaronburtle aaronburtle left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks good once comments are addressed!

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.

[Known Issue]: Autoentities fail when table names generate duplicate GraphQL operations

5 participants