Azure / Azure/data-api-builder

[Bug]: GraphQL SchemaConverter throws “No relationship exists” when two relationships are present

Open
#2,540 2 comments 0 reactions 1 assignee Assigned to @abhishekkumams View on GitHub
2.x
Dominant language
C#
Stars
1.5k
Forks
370
Avg merge
3d 17h
Merged PRs (30d)
8

Description

![Image](https://github.com/user-attachments/assets/c26fef9b-088c-492b-9933-7626b599cb18)

## Query

```graphql
query a {
characters {
items {
Name
}
}
}
```

## Error

```
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1]
Executed endpoint 'Hot Chocolate GraphQL Pipeline'
fail: Microsoft.AspNetCore.Server.Kestrel[13]
Connection id "0HN9S4N57VFC1", Request id "0HN9S4N57VFC1:00000003": An unhandled exception was thrown by the application.
Azure.DataApiBuilder.Service.Exceptions.DataApiBuilderException: No relationship exists between Character and Actor
at Azure.DataApiBuilder.Service.GraphQLBuilder.Sql.SchemaConverter.FindNullabilityOfRelationship(String entityName, DatabaseObject databaseObject, String targetEntityName) in /_/src/Service.GraphQLBuilder/Sql/SchemaConverter.cs:line 470
at Azure.DataApiBuilder.Service.GraphQLBuilder.Sql.SchemaConverter.GenerateFieldForRelationship(String entityName, DatabaseObject databaseObject, RuntimeEntities entities, String relationshipName, EntityRelationship relationship) in /_/src/Service.GraphQLBuilder/Sql/SchemaConverter.cs:line 276
at Azure.DataApiBuilder.Service.GraphQLBuilder.Sql.SchemaConverter.CreateObjectTypeDefinitionForTableOrView(String entityName, DatabaseObject databaseObject, Entity configEntity, RuntimeEntities entities, IEnumerable`1 rolesAllowedForEntity, IDictionary`2 rolesAllowedForFields) in /_/src/Service.GraphQLBuilder/Sql/SchemaConverter.cs:line 195
at Azure.DataApiBuilder.Service.GraphQLBuilder.Sql.SchemaConverter.GenerateObjectTypeDefinitionForDatabaseObject(String entityName, DatabaseObject databaseObject, Entity configEntity, RuntimeEntities entities, IEnumerable`1 rolesAllowedForEntity, IDictionary`2 rolesAllowedForFields) in /_/src/Service.GraphQLBuilder/Sql/SchemaConverter.cs:line 56
at Azure.DataApiBuilder.Core.Services.GraphQLSchemaCreator.GenerateSqlGraphQLObjects(RuntimeEntities entities, Dictionary`2 inputObjects) in /_/src/Core/Services/GraphQLSchemaCreator.cs:line 214
at Azure.DataApiBuilder.Core.Services.GraphQLSchemaCreator.GenerateGraphQLObjects() in /_/src/Core/Services/GraphQLSchemaCreator.cs:line 609
at Azure.DataApiBuilder.Core.Services.GraphQLSchemaCreator.InitializeSchemaAndResolvers(ISchemaBuilder schemaBuilder) in /_/src/Core/Services/GraphQLSchemaCreator.cs:line 155
at Azure.DataApiBuilder.Service.Startup.<>c.b__14_0(IServiceProvider serviceProvider, ISchemaBuilder schemaBuilder) in /_/src/Service/Startup.cs:line 237
at HotChocolate.Execution.RequestExecutorResolver.CreateSchemaAsync(NameString schemaName, RequestExecutorSetup options, RequestExecutorOptions executorOptions, IServiceProvider serviceProvider, TypeModuleChangeMonitor typeModuleChangeMonitor, CancellationToken cancellationToken)
at HotChocolate.Execution.RequestExecutorResolver.CreateSchemaServicesAsync(NameString schemaN
```

### Error message

```
No relationship exists between Character and Actor
```

There is a relationship between Character and Actor. This error is wrong.

### Observation

There are TWO relationships. If I remove EITHER it starts working.

## Configuration

```json
{
"$schema": "https://github.com/Azure/data-api-builder/releases/download/v1.3.19/dab.draft.schema.json",
"data-source": {
"database-type": "mssql",
"connection-string": "{conn-string}",
"options": {
"set-session-context": false
}
},
"runtime": {
"host": {
"cors": {
"origins": [],
"allow-credentials": false
},
"authentication": {
"provider": "StaticWebApps"
},
"mode": "development"
}
},
"entities": {
"Character": {
"source": {
"object": "dbo.Character",
"type": "table"
},
"permissions": [
{
"role": "anonymous",
"actions": [
{
"action": "*"
}
]
}
],
"relationships": {
"Actor": {
"cardinality": "many",
"target.entity": "Actor",
"source.fields": [
"ActorId"
],
"target.fields": [
"Id"
],
"linking.source.fields": [],
"linking.target.fields": []
}
}
},
"Character_Species": {
"source": {
"object": "dbo.Character_Species",
"type": "table"
},
"permissions": [
{
"role": "anonymous",
"actions": [
{
"action": "*"
}
]
}
],
"relationships": {
"Character": {
"cardinality": "many",
"target.entity": "Character",
"source.fields": [
"CharacterId"
],
"target.fields": [
"Id"
],
"linking.source.fields": [],
"linking.target.fields": []
}
}
},
"Actor": {
"source": {
"object": "dbo.Actor",
"type": "table"
},
"permissions": [
{
"role": "anonymous",
"actions": [
{
"action": "*"
}
]
}
]
}
}
}
```

## Database schema

```sql
SET NOCOUNT ON

use [trek];

-- Create Login
IF NOT EXISTS (SELECT * FROM sys.server_principals WHERE name = 'DabLogin')
CREATE LOGIN [DabLogin] WITH PASSWORD = 'P@ssw0rd!';
ALTER SERVER ROLE sysadmin ADD MEMBER [DabLogin];

-- Create User
IF NOT EXISTS (SELECT * FROM sys.database_principals WHERE name = 'DabUser')
CREATE USER [DabUser] FOR LOGIN [DabLogin];
EXEC sp_addrolemember 'db_owner', 'DabUser';

-- Drop tables in reverse order of creation due to foreign key dependencies
DROP TABLE IF EXISTS Character_Species;
DROP TABLE IF EXISTS Series_Character;
DROP TABLE IF EXISTS Character;
DROP TABLE IF EXISTS Species;
DROP TABLE IF EXISTS Actor;
DROP TABLE IF EXISTS Series;

-- create tables
CREATE TABLE Series (
Id INT PRIMARY KEY,
Name NVARCHAR(255) NOT NULL
);

CREATE TABLE Actor (
Id INT PRIMARY KEY,
Name NVARCHAR(255) NOT NULL,
[BirthYear] INT NOT NULL
);

CREATE TABLE Species (
Id INT PRIMARY KEY,
Name NVARCHAR(255) NOT NULL
);

CREATE TABLE Character (
Id INT PRIMARY KEY,
Name NVARCHAR(255) NOT NULL,
ActorId INT NOT NULL,
Stardate DECIMAL(10, 2),
FOREIGN KEY (ActorId) REFERENCES Actor(Id)
);

CREATE TABLE Series_Character (
SeriesId INT,
CharacterId INT,
Role VARCHAR(500),
FOREIGN KEY (SeriesId) REFERENCES Series(Id),
FOREIGN KEY (CharacterId) REFERENCES Character(Id),
PRIMARY KEY (SeriesId, CharacterId)
);

CREATE TABLE Character_Species (
CharacterId INT,
SpeciesId INT,
FOREIGN KEY (CharacterId) REFERENCES Character(Id),
FOREIGN KEY (SpeciesId) REFERENCES Species(Id),
PRIMARY KEY (CharacterId, SpeciesId)
);
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.