C
C#4w ago
Kuurama

✅ Possible bug in EFCore nested complex properties as record type

Hi, I'm facing an issue while binding the following data models:
public sealed class BeatLeaderScore : AbstractScore
{
public required BeatLeaderScoreId? BeatLeaderScoreId { get; init; }
public required ScoreStatistics? Statistics { get; init; }
}

public class BeatLeaderScoreConfiguration : IEntityTypeConfiguration<BeatLeaderScore>
{
public void Configure(EntityTypeBuilder<BeatLeaderScore> builder)
{
builder.HasBaseType<AbstractScore>();
builder.ComplexProperty(x => x.Statistics, x =>
{
x.ComplexProperty(y => y.WinTracker, y =>
{
y.ComplexProperty(z => z.AverageHeadPosition);
});
x.ComplexProperty(y => y.HitTracker);
x.ComplexProperty(y => y.AccuracyTracker);
x.ComplexProperty(y => y.ScoreGraphTracker);
});
builder.Property(x => x.BeatLeaderScoreId)
.HasConversion<int?>(from => from, to => BeatLeaderScoreId.CreateUnsafe(to));
}
}

public record ScoreStatistics(
WinTracker WinTracker,
HitTracker HitTracker,
AccuracyTracker AccuracyTracker,
ScoreGraphTracker ScoreGraphTracker
);

public readonly record struct AverageHeadPosition(float X, float Y, float Z);

public record WinTracker(
bool IsWin,
float EndTime,
int PauseCount,
float TotalPauseDuration,
float JumpDistance,
float AverageHeight,
int TotalScore,
int MaxScore
)
{
public required AverageHeadPosition? AverageHeadPosition { get; init; }
}

public record HitTracker(
int Max115Streak,
float LeftTiming,
float RightTiming,
int LeftMiss,
int RightMiss,
int LeftBadCuts,
int RightBadCuts,
int LeftBombs,
int RightBombs
);

public record AccuracyTracker(
float AccRight,
float AccLeft,
float LeftPreSwing,
float RightPreSwing,
float LeftPostSwing,
float RightPostSwing,
float LeftTimeDependence,
float RightTimeDependence,
IReadOnlyList<float> LeftAverageCutGraphGrid,
IReadOnlyList<float> RightAverageCutGraphGrid,
IReadOnlyList<float> AccuracyGrid
);

public record ScoreGraphTracker(List<float> Graph);
public sealed class BeatLeaderScore : AbstractScore
{
public required BeatLeaderScoreId? BeatLeaderScoreId { get; init; }
public required ScoreStatistics? Statistics { get; init; }
}

public class BeatLeaderScoreConfiguration : IEntityTypeConfiguration<BeatLeaderScore>
{
public void Configure(EntityTypeBuilder<BeatLeaderScore> builder)
{
builder.HasBaseType<AbstractScore>();
builder.ComplexProperty(x => x.Statistics, x =>
{
x.ComplexProperty(y => y.WinTracker, y =>
{
y.ComplexProperty(z => z.AverageHeadPosition);
});
x.ComplexProperty(y => y.HitTracker);
x.ComplexProperty(y => y.AccuracyTracker);
x.ComplexProperty(y => y.ScoreGraphTracker);
});
builder.Property(x => x.BeatLeaderScoreId)
.HasConversion<int?>(from => from, to => BeatLeaderScoreId.CreateUnsafe(to));
}
}

public record ScoreStatistics(
WinTracker WinTracker,
HitTracker HitTracker,
AccuracyTracker AccuracyTracker,
ScoreGraphTracker ScoreGraphTracker
);

public readonly record struct AverageHeadPosition(float X, float Y, float Z);

public record WinTracker(
bool IsWin,
float EndTime,
int PauseCount,
float TotalPauseDuration,
float JumpDistance,
float AverageHeight,
int TotalScore,
int MaxScore
)
{
public required AverageHeadPosition? AverageHeadPosition { get; init; }
}

public record HitTracker(
int Max115Streak,
float LeftTiming,
float RightTiming,
int LeftMiss,
int RightMiss,
int LeftBadCuts,
int RightBadCuts,
int LeftBombs,
int RightBombs
);

public record AccuracyTracker(
float AccRight,
float AccLeft,
float LeftPreSwing,
float RightPreSwing,
float LeftPostSwing,
float RightPostSwing,
float LeftTimeDependence,
float RightTimeDependence,
IReadOnlyList<float> LeftAverageCutGraphGrid,
IReadOnlyList<float> RightAverageCutGraphGrid,
IReadOnlyList<float> AccuracyGrid
);

public record ScoreGraphTracker(List<float> Graph);
The error message I'm getting is the following (when running a migration):
The Entity Framework tools version '9.0.5' is older than that of the runtime '10.0.0-rc.2.25502.107'. Update the tools for the latest features and bug fixes. See https://aka.ms/AAc1fbw for more information.
Unable to create a 'DbContext' of type 'ServerDbContext'. The exception 'No suitable constructor was found for the type 'BeatLeaderScore.Statistics#ScoreStatistics'. The following constructors had parameters that could not be bound to properties of the type:
Cannot bind 'WinTracker', 'HitTracker', 'AccuracyTracker', 'ScoreGraphTracker' in 'BeatLeaderScore.Statistics#ScoreStatistics(WinTracker WinTracker, HitTracker HitTracker, AccuracyTracker AccuracyTracker, ScoreGraphTracker ScoreGraphTracker)'
Cannot bind 'original' in 'BeatLeaderScore.Statistics#ScoreStatistics(ScoreStatistics original)'
Note that only mapped properties can be bound to constructor parameters. Navigations to related entities, including references to owned types, cannot be bound.' was thrown while attempting to create an instance. For the different patterns supported at design time, see https://go.microsoft.com/fwlink/?linkid=851728
The Entity Framework tools version '9.0.5' is older than that of the runtime '10.0.0-rc.2.25502.107'. Update the tools for the latest features and bug fixes. See https://aka.ms/AAc1fbw for more information.
Unable to create a 'DbContext' of type 'ServerDbContext'. The exception 'No suitable constructor was found for the type 'BeatLeaderScore.Statistics#ScoreStatistics'. The following constructors had parameters that could not be bound to properties of the type:
Cannot bind 'WinTracker', 'HitTracker', 'AccuracyTracker', 'ScoreGraphTracker' in 'BeatLeaderScore.Statistics#ScoreStatistics(WinTracker WinTracker, HitTracker HitTracker, AccuracyTracker AccuracyTracker, ScoreGraphTracker ScoreGraphTracker)'
Cannot bind 'original' in 'BeatLeaderScore.Statistics#ScoreStatistics(ScoreStatistics original)'
Note that only mapped properties can be bound to constructor parameters. Navigations to related entities, including references to owned types, cannot be bound.' was thrown while attempting to create an instance. For the different patterns supported at design time, see https://go.microsoft.com/fwlink/?linkid=851728
I'm trying to update my system, maybe it is resolved with that new version.
15 Replies
Kuurama
KuuramaOP4w ago
It works (assuming I properly configure the required member to make the nullable complex types boundable) if I make the ScoreStatistics record a class with properties instead. It feels like we can't bind a record as a complex type if it also contains other complex types. But maybe my understanding is wrong, I also find the nullable complex type feature confusing. I expected a discriminator as a bool like "isNull" instead of relying on some properties. And even then, I don't know how to properly use the .HasDiscriminator() either. It's fairly hard to have the expected behavior, sometimes, the properties don't even get mapped in the database, it just gets persisted as null. Any pro here? The issue is the same if I remove the nullability of ScoreStatistics btw. It doen't seem related to this.
JakenVeina
JakenVeina4w ago
if swapping ScoreStatistics from a record to a class makes it all work, then that sure sounds like a bug to me try swapping it to a class and also keeping all the constructor parameter names as PascalCase instead of camelCase does it still fail? I'm gonna make a guess that it will indicating it's not an issue with records, per-se, it's that records decided it was a good idea to break the existing naming conventions that people (and libraries like EF) rely on. EF matches this for records normally, but perhaps they've missed a scenario that only occurs when using records as complex types, or only using them in a nested fashion
Unknown User
Unknown User4w ago
Message Not Public
Sign In & Join Server To View
Kuurama
KuuramaOP4w ago
complex types aren't entity types I don't give a dam about tracking those either X) i use a non tracking default
Unknown User
Unknown User4w ago
Message Not Public
Sign In & Join Server To View
Kuurama
KuuramaOP4w ago
I know it works with a class
Unknown User
Unknown User4w ago
Message Not Public
Sign In & Join Server To View
Kuurama
KuuramaOP4w ago
I don't want a class
Unknown User
Unknown User4w ago
Message Not Public
Sign In & Join Server To View
Unknown User
Unknown User4w ago
Message Not Public
Sign In & Join Server To View
Kuurama
KuuramaOP4w ago
this works I assume it's only when it's in a nested fashion. Because my other records as complex types just works. (on my other entities)
Unknown User
Unknown User4w ago
Message Not Public
Sign In & Join Server To View
Kuurama
KuuramaOP4w ago
Yeah that's what I knew I had to do. I didn't want to (laziness), that's why I came here first just in case X)
Kuurama
KuuramaOP3w ago
GitHub
Nested complex types can't be bound if the parent puts it in positi...
Bug description Given models that have nested complex types: Foo -&gt; FooInfo -&gt; Bar The positional parameters in primary constructor variant: record FooInfo(string Name, Bar Bar); fails the mi...

Did you find this page helpful?