Skip to content

Value Conversion of custom struct type throws exception if it doesn't implement == and != operators #12290

Closed
@gojanpaolo

Description

@gojanpaolo
Exception message: 

The binary operator Equal is not defined for the types 'ExceptionEqualIsNotDefined.Fuel' and 'ExceptionEqualIsNotDefined.Fuel'.

Stack trace:

   at Microsoft.EntityFrameworkCore.Metadata.Internal.ClrAccessorFactory`1.Create(PropertyInfo propertyInfo, IPropertyBase propertyBase)
   at Microsoft.EntityFrameworkCore.Metadata.Internal.ClrAccessorFactory`1.Create(IPropertyBase property)
   at Microsoft.EntityFrameworkCore.Metadata.Internal.PropertyBase.<>c.<get_Getter>b__34_0(PropertyBase p)
   at Microsoft.EntityFrameworkCore.Internal.NonCapturingLazyInitializer.EnsureInitialized[TParam,TValue](TValue& target, TParam param, Func`2 valueFactory)
   at Microsoft.EntityFrameworkCore.Metadata.Internal.PropertyBase.get_Getter()
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.ReadPropertyValue(IPropertyBase propertyBase)
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.ChangeDetector.DetectChanges(InternalEntityEntry entry)
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.ChangeDetector.DetectChanges(IStateManager stateManager)
   at Microsoft.EntityFrameworkCore.ChangeTracking.ChangeTracker.DetectChanges()
   at Microsoft.EntityFrameworkCore.DbContext.TryDetectChanges()
   at Microsoft.EntityFrameworkCore.DbContext.SaveChanges(Boolean acceptAllChangesOnSuccess)
   at Microsoft.EntityFrameworkCore.DbContext.SaveChanges()
   at ExceptionEqualIsNotDefined.Tests.Test() in 

Steps to reproduce

public class Tests
{
    [Fact]
    public void Test()
    {
        using (var connection = new SqliteConnection("DataSource=:memory:"))
        {
            connection.Open();

            var options = new DbContextOptionsBuilder<Context>()
                .UseSqlite(connection)
                .Options;

            using (var context = new Context(options))
            {
                context.Database.EnsureCreated();
            }

            using (var context = new Context(options))
            {
                context.Add(new Load());
                context.SaveChanges(); //throws exception here
            }
        }
    }
}

public class Context : DbContext
{
    public Context(DbContextOptions options) : base(options) { }

    public DbSet<Load> Load { get; private set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Load>(e =>
        {
            e.Property(l => l.Fuel)
                .HasConversion(
                    f => f.Volume,
                    v => new Fuel(v));
        });
    }
}

public class Load
{
    public int LoadId { get; private set; }

    public Fuel Fuel { get; set; }
}

public struct Fuel
{
    public Fuel(double volume)
    {
        Volume = volume;
    }

    public double Volume { get; }

    // Uncomment below to get rid of exception.
    //public static bool operator ==(Fuel left, Fuel right)
    //{
    //    return left.Volume == right.Volume;
    //}

    //public static bool operator !=(Fuel left, Fuel right)
    //{
    //    return left.Volume != right.Volume;
    //}

    //// Need to override Equals and GetHashCode to get rid of warning.
    //public override bool Equals(object obj)
    //{
    //    if (obj == null || GetType() != obj.GetType())
    //    {
    //        return false;
    //    }

    //    return Volume.Equals(((Fuel)obj).Volume);
    //}

    //public override int GetHashCode()
    //{
    //    return Volume.GetHashCode();
    //}
}

Further technical details

EF Core version: 2.1.0
Database Provider: Microsoft.EntityFrameworkCore.Sqlite
Operating system: Win7
IDE: Visual Studio 2017 15.7.2

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions