Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't ignore an ImmutableArray<> property in entity configuration #35329

Open
ErroneousFatality opened this issue Dec 13, 2024 · 3 comments
Open

Comments

@ErroneousFatality
Copy link

ErroneousFatality commented Dec 13, 2024

I want to have a pass-through property in my code for developer usage convenience, thus I want to ignore the property in the entity configuration because I don't need it mapped to the database.
EFCore throws an exception during migration building saying it can't use the property because it doesn't know how to compare the generic immutable array type with an object.

When I change the ignored property's type to IReadOnlyList<Role>/IReadOnlyCollection<Role> everything works fine.

Code examples

public sealed class Example 
{
    public Guid Id { get; private set; }

    public ImmutableArray<Role> Roles { 
        get => Enum.GetValues<Role>().Where(flag => RoleFlags.HasFlag(flag)).ToImmutableArray(); 
        internal set => RoleFlags = value.Aggregate((flags, role) => flags | role);
    }
    public Role RoleFlags { get; private set; }
}
internal sealed class ExampleConfiguration : IEntityTypeConfiguration<Example>
{
    public void Configure(EntityTypeBuilder<Example> example)
    {
        example.Ignore(e => e.Roles);
    }
}
[Flags]
public enum Role : byte
{
    Administrator = 1,
    Customer = 2
}

Stack trace and verbose output

Microsoft.EntityFrameworkCore.Design.OperationException: Unable to create a 'DbContext' of type 'PostgreSqlDataContext'. The exception 'Exception has been thrown by the target of an invocation.' was thrown while attempting to create an instance. For the different patterns supported at design time, see https://go.microsoft.com/fwlink/?linkid=851728
 ---> System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation.
 ---> System.InvalidOperationException: Reference equality is not defined for the types 'System.Collections.Immutable.ImmutableArray`1[Domain.Entities.Users.Role]' and 'System.Object'.
   at System.Linq.Expressions.Expression.ReferenceEqual(Expression left, Expression right)
   at Npgsql.EntityFrameworkCore.PostgreSQL.Storage.ValueConversion.NpgsqlArrayConverter`3.ArrayConversionExpression[TInput,TOutput,TConcreteOutput](LambdaExpression elementConversionExpression)
   at Npgsql.EntityFrameworkCore.PostgreSQL.Storage.ValueConversion.NpgsqlArrayConverter`3..ctor(ValueConverter elementConverter)
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
   at System.Reflection.MethodBaseInvoker.InvokeDirectByRefWithFewArgs(Object obj, Span`1 copyOfArgs, BindingFlags invokeAttr)
   --- End of inner exception stack trace ---
   at System.Reflection.MethodBaseInvoker.InvokeDirectByRefWithFewArgs(Object obj, Span`1 copyOfArgs, BindingFlags invokeAttr)
   at System.Reflection.MethodBaseInvoker.InvokeWithOneArg(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at System.Reflection.RuntimeConstructorInfo.Invoke(BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at System.RuntimeType.CreateInstanceImpl(BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo culture)
   at System.Activator.CreateInstance(Type type, Object[] args)
   at Npgsql.EntityFrameworkCore.PostgreSQL.Storage.Internal.Mapping.NpgsqlArrayTypeMapping`3.CreateParameters(String storeType, RelationalTypeMapping elementMapping)
   at Npgsql.EntityFrameworkCore.PostgreSQL.Storage.Internal.Mapping.NpgsqlArrayTypeMapping`3..ctor(String storeType, RelationalTypeMapping elementTypeMapping)
   at Npgsql.EntityFrameworkCore.PostgreSQL.Storage.Internal.Mapping.NpgsqlArrayTypeMapping`3..ctor(RelationalTypeMapping elementTypeMapping)
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
   at System.Reflection.MethodBaseInvoker.InvokeDirectByRefWithFewArgs(Object obj, Span`1 copyOfArgs, BindingFlags invokeAttr)
   --- End of inner exception stack trace ---
   at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.CreateContext(String contextType, KeyValuePair`2 contextPair)
   at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.CreateContext(String contextType)
   at Microsoft.EntityFrameworkCore.Design.Internal.MigrationsOperations.AddMigration(String name, String outputDir, String contextType, String namespace, Boolean dryRun)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigrationImpl(String name, String outputDir, String contextType, String namespace, Boolean dryRun)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigration.<>c__DisplayClass0_0.<.ctor>b__0()
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.<>c__DisplayClass3_0`1.<Execute>b__0()
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)
Unable to create a 'DbContext' of type 'PostgreSqlDataContext'. The exception 'Exception has been thrown by the target of an invocation.' was thrown while attempting to create an instance. For the different patterns supported at design time, see https://go.microsoft.com/fwlink/?linkid=851728

Provider and version information

EF Core version: 9.0.0
Database provider: Npgsql.EntityFrameworkCore.PostgreSQL 9.0.2
Target framework: .NET 9.0
Operating system: Windows 11 24H2
IDE: Visual Studio 2022 17.12.3

@ErroneousFatality ErroneousFatality changed the title Can't ignore a ImmutableArray<> property in entity configuration Can't ignore an ImmutableArray<> property in entity configuration Dec 13, 2024
@AndriySvyryd
Copy link
Member

How do you apply the configuration? Place a breakpoint in ExampleConfiguration.Configure and check that it's hit.

@ErroneousFatality
Copy link
Author

ErroneousFatality commented Dec 17, 2024

It's hit.
I use ModelBuilder.ApplyConfigurationFromAssembly(...); to apply my configurations.

public sealed class PostgreSqlDataContext: DbContext
{
    // Entities
    public DbSet<Example> Examples => Set<Example>();

    // Constructors
    public PostgreSqlDataContext(DbContextOptions options) 
        : base(options) { }

    // Methods
    protected override void OnModelCreating(ModelBuilder model)
    {
        base.OnModelCreating(model);
        model.ApplyConfigurationsFromAssembly(typeof(PostgreSqlDataContext).Assembly);
    }
}

When I change the Roles' type in my entity to IReadOnlyList<Role> and remove the ignore command in the configuration, it shows up in the migration; when I leave the ignore it doesn't get mapped.
Only when I use the ImmutableArray with or without the ignore does the migration creation break.

@AndriySvyryd
Copy link
Member

This seems to be Npgsql-specific. @roji can you take a look?

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

No branches or pull requests

3 participants