dotnet / dotnet/Scaffolding

Minimal API Scaffold does not handle `EF Model Composite Keys` correctly

Open
#1,965 0 comments 0 reactions 0 assignees View on GitHub
0 - Backlog area-scaffolding Feature
Dominant language
C#
Stars
818
Forks
260
Avg merge
1d 8h
Merged PRs (30d)
10

Description

Scaffolding Minimal API endpoints from a model with composite key (`Key1` and `Key2`) generates a code that ignores the second key (`Key2`).

### Steps to reproduce

1. Create simple model

``` c#
using Microsoft.EntityFrameworkCore;

[PrimaryKey("Key1", "Key2")]
public class ComplexModel
{
public int Key1 { get; set; }
public int Key2 { get; set; }

public string Name { get; set; }
}
```

2. Scaffold minimal `api with read/write endpoints using Entity Framework`. Code generated will look like this:

``` c#
routes.MapGet("/api/ComplexModel/{id}", async (int Key1, SampleModelContext db) =>
{
return await db.ComplexModel.FindAsync(Key1)
is ComplexModel model
? Results.Ok(model)
: Results.NotFound();
})
.WithName("GetComplexModelById");

routes.MapPut("/api/ComplexModel/{id}", async (int Key1, ComplexModel complexModel, SampleModelContext db) =>
{
var foundModel = await db.ComplexModel.FindAsync(Key1);

if (foundModel is null)
{
return Results.NotFound();
}
//update model properties here

await db.SaveChangesAsync();

return Results.NoContent();
})
.WithName("UpdateComplexModel");

routes.MapDelete("/api/ComplexModel/{id}", async (int Key1, SampleModelContext db) =>
{
if (await db.ComplexModel.FindAsync(Key1) is ComplexModel complexModel)
{
db.ComplexModel.Remove(complexModel);
await db.SaveChangesAsync();
return Results.Ok(complexModel);
}

return Results.NotFound();
})
.WithName("DeleteComplexModel");
```

Note the calls to the `FindAsync` only includes the `Key1` that cause the following exception:

```
System.ArgumentException: Entity type 'ComplexModel' is defined with a 2-part composite key, but 1 values were passed to the 'Find' method.
at Microsoft.EntityFrameworkCore.Internal.EntityFinder`1.FindTracked(Object[] keyValues, IReadOnlyList`1& keyProperties)
at Microsoft.EntityFrameworkCore.Internal.EntityFinder`1.FindAsync(Object[] keyValues, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Internal.InternalDbSet`1.FindAsync(Object[] keyValues)
at WebApplication1.ComplexModelEndpoints.<>c.<b__0_2>d.MoveNext() in C:\Users\brolivei\Source\Repos\WebApplication1\WebApplication1\ComplexModelEndpoints.cs:line 26
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Http.RequestDelegateFactory.ExecuteTaskResult[T](Task`1 task, HttpContext httpContext)
at Microsoft.AspNetCore.Http.RequestDelegateFactory.<>c__DisplayClass87_2.<b__2>d.MoveNext()
```

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.