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

Replacing Owned Entity that contains an enum value with .HasConversion<string> throws exception during SaveChanges #28763

Closed
bperc2 opened this issue Aug 17, 2022 · 0 comments · Fixed by #29064
Labels
area-save-changes closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. customer-reported regression type-bug
Milestone

Comments

@bperc2
Copy link

bperc2 commented Aug 17, 2022

After upgrading to preview versions of 7.0, I started encountering InvalidCastExceptions when saving changes to some of my entities. The specific scenario appears to be:

  1. Replace an instance of an owned entity with a new instance
  2. The owned entity contains an enum property that has been converted into a string
  3. The value of that enum property has changed since it was loaded from the database

This all worked fine in EF Core 6.0 and 7.0.0-preview.3.22175.1. Preview 4 and beyond exhibit the issue.

Here is a runnable example to demonstrate.

using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;


await using var context = new AppDbContext();
await context.Database.EnsureDeletedAsync();
await context.Database.EnsureCreatedAsync();

// Setup
var project = new Project() { Title = "Test Project" };
project.Form.Quesion2 = MultipleChoiceOptions.A;
context.Projects.Add(project);

context.SaveChanges();

var project2 = context.Projects.First();
project2.Form.Quesion2 = MultipleChoiceOptions.B;
// This works fine
context.SaveChanges();

var project3 = context.Projects.First();
var replacementForm = new Form() { Question1 = "Updated", Quesion2 = MultipleChoiceOptions.B };
project3.Form = replacementForm;
// This also works fine because the value of the enum property didn't change
context.SaveChanges();

var project4 = context.Projects.First();
var replacementForm2 = new Form() { Quesion2 = MultipleChoiceOptions.C };
project4.Form = replacementForm2;
// This throws
context.SaveChanges();



public class AppDbContext : DbContext
{
    public DbSet<Project> Projects { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) 
        => optionsBuilder
            .UseSqlServer("...")
            .LogTo(Console.WriteLine, LogLevel.Information)
            .EnableSensitiveDataLogging();

    protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder)
    {
        configurationBuilder
            .Properties<Enum>()
            .HaveConversion<string>();
    }

    protected override void OnModelCreating(ModelBuilder builder)
    {
        builder.Entity<Project>(e =>
        {
            e.OwnsOne(p => p.Form, pf =>
            {

            });
        });
    }

}
    public class Project
    {
        public int Id { get; set; }
        public string Title { get; set; }
        public Form Form { get; set; } = new();
    }

    public class Form
    {
        public string Question1 { get; set; } = "";
        public MultipleChoiceOptions? Quesion2 { get; set; }
    }

    public enum MultipleChoiceOptions
    {
        A,
        B,
        C,
        D
    }

Include stack traces

Exception message and stack trace

System.InvalidCastException
  HResult=0x80004002
  Message=Unable to cast object of type 'MultipleChoiceOptions' to type 'System.String'.
  Source=Microsoft.EntityFrameworkCore
  StackTrace:
   at Microsoft.EntityFrameworkCore.ChangeTracking.ValueComparer`1.Equals(Object left, Object right)
   at Microsoft.EntityFrameworkCore.Update.ModificationCommand.ColumnValuePropagator.TryPropagate(IColumnMapping mapping, IUpdateEntry entry)
   at Microsoft.EntityFrameworkCore.Update.ModificationCommand.GenerateColumnModifications()
   at Microsoft.EntityFrameworkCore.Update.ModificationCommand.get_ColumnModifications()
   at Microsoft.EntityFrameworkCore.Update.Internal.CommandBatchPreparer.<BatchCommands>d__8.MoveNext()
   at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.Execute(IEnumerable`1 commandBatches, IRelationalConnection connection)
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChanges(IList`1 entriesToSave)
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChanges(StateManager stateManager, Boolean acceptAllChangesOnSuccess)
   at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.Execute[TState,TResult](TState state, Func`3 operation, Func`3 verifySucceeded)
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChanges(Boolean acceptAllChangesOnSuccess)
   at Microsoft.EntityFrameworkCore.DbContext.SaveChanges(Boolean acceptAllChangesOnSuccess)

Provider and version information

EF Core version: 7.0.0-preview.4.22229.2 - 7.0.0-preview.7.22376.2
Database provider: Microsoft.EntityFrameworkCore.SqlServer
Target framework: .NET 6.0
Operating system: Windows 10
IDE: Visual Studio 2022 17.3.0

@ajcvickers ajcvickers added this to the 7.0.0 milestone Aug 24, 2022
@AndriySvyryd AndriySvyryd added the closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. label Sep 12, 2022
@AndriySvyryd AndriySvyryd removed their assignment Sep 12, 2022
@ajcvickers ajcvickers modified the milestones: 7.0.0, 7.0.0-rc2 Sep 14, 2022
@ajcvickers ajcvickers modified the milestones: 7.0.0-rc2, 7.0.0 Nov 5, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-save-changes closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. customer-reported regression type-bug
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants