Cannot convert between types that have an implicit cast in Indexer Properties
- Dominant language
- C#
- Stars
- 14.8k
- Forks
- 3.4k
- PR merge metrics
- PR metrics pending
Description
Json serializers will often convert the numbers in a dictionary to the smallest type, "90" will be converted to byte. When this dictionary has indexerProperty, the conversion will fail if the deserialized value has not exactly the same type as the indexerProperty type ( even if there is an implicit conversion like int=>long ).
### Code
```C#
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
public class User
{
public int Id { get; set; }
public Dictionary Data { get; set; }
public long Number { get; set; }
}
public class SqlServerDbContext : DbContext
{
public SqlServerDbContext(DbContextOptions options) : base(options)
{ }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
var etb = modelBuilder.Entity();
etb.HasKey(x => x.Id);
etb.Property(x => x.Number);
etb.OwnsOne(x => x.Data, x =>
{
x.IndexerProperty(typeof(long), "Number");
});
}
}
class Program
{
static void Main(string[] args)
{
var sc = new ServiceCollection();
var guid = Guid.NewGuid();
sc.AddDbContext(op => op.UseSqlServer(@"Server=(localdb)\MSSQLLocalDB;Integrated Security=true;DataBase=" + guid));
using (var provider = sc.BuildServiceProvider())
{
using (var scope = provider.CreateScope())
using (var dbcontext = scope.ServiceProvider.GetService())
{
dbcontext.Database.EnsureCreated();
}
var user = new User()
{
Number = 5
};
using (var scope = provider.CreateScope())
using (var dbcontext = scope.ServiceProvider.GetService())
{
dbcontext.Set().Add(user);
dbcontext.SaveChanges();
}
var user2 = new User()
{
Data = new Dictionary() { { "Number", 5 } }
};
using (var scope = provider.CreateScope())
using (var dbcontext = scope.ServiceProvider.GetService())
{
dbcontext.Set().Add(user2);
dbcontext.SaveChanges();
}
}
}
}
```
### Stack traces
```
System.InvalidCastException
HResult=0x80004002
Message=Unable to cast object of type 'System.Int32' to type 'System.Int64'.
Source=Microsoft.EntityFrameworkCore
StackTrace:
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.OriginalValues..ctor(InternalEntityEntry entry)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.EnsureOriginalValues()
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntrySubscriber.SnapshotAndSubscribe(InternalEntityEntry entry)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.StartTracking(InternalEntityEntry entry)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.SetEntityState(EntityState oldState, EntityState newState, Boolean acceptChanges, Boolean modifyProperties)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.SetEntityState(EntityState entityState, Boolean acceptChanges, Boolean modifyProperties, Nullable`1 forceStateWhenUnknownKey)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.EntityGraphAttacher.PaintAction(EntityEntryGraphNode`1 node)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.EntityEntryGraphIterator.TraverseGraph[TState](EntityEntryGraphNode`1 node, Func`2 handleNode)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.EntityEntryGraphIterator.TraverseGraph[TState](EntityEntryGraphNode`1 node, Func`2 handleNode)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.EntityGraphAttacher.AttachGraph(InternalEntityEntry rootEntry, EntityState targetState, EntityState storeGeneratedWithKeySetTargetState, Boolean forceStateWhenUnknownKey)
at Microsoft.EntityFrameworkCore.Internal.InternalDbSet`1.SetEntityState(InternalEntityEntry entry, EntityState entityState)
at Microsoft.EntityFrameworkCore.Internal.InternalDbSet`1.Add(TEntity entity)
at Program.Main(String[] args)
This exception was originally thrown at this call stack:
Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.OriginalValues.OriginalValues(Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry)
Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.EnsureOriginalValues()
Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntrySubscriber.SnapshotAndSubscribe(Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry)
Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.StartTracking(Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry)
Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.SetEntityState(Microsoft.EntityFrameworkCore.EntityState, Microsoft.EntityFrameworkCore.EntityState, bool, bool)
Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.SetEntityState(Microsoft.EntityFrameworkCore.EntityState, bool, bool, Microsoft.EntityFrameworkCore.EntityState?)
Microsoft.EntityFrameworkCore.ChangeTracking.Internal.EntityGraphAttacher.PaintAction(Microsoft.EntityFrameworkCore.ChangeTracking.EntityEntryGraphNode<(Microsoft.EntityFrameworkCore.EntityState TargetState, Microsoft.EntityFrameworkCore.EntityState StoreGenTargetState, bool Force)>)
Microsoft.EntityFrameworkCore.ChangeTracking.Internal.EntityEntryGraphIterator.TraverseGraph(Microsoft.EntityFrameworkCore.ChangeTracking.EntityEntryGraphNode, System.Func, bool>)
Microsoft.EntityFrameworkCore.ChangeTracking.Internal.EntityEntryGraphIterator.TraverseGraph(Microsoft.EntityFrameworkCore.ChangeTracking.EntityEntryGraphNode, System.Func, bool>)
Microsoft.EntityFrameworkCore.ChangeTracking.Internal.EntityGraphAttacher.AttachGraph(Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry, Microsoft.EntityFrameworkCore.EntityState, Microsoft.EntityFrameworkCore.EntityState, bool)
...
[Call Stack Truncated]
```
### Provider and version information
EF Core version: 6.0.5
Database provider: Microsoft.EntityFrameworkCore.SqlServer
Target framework: .NET 6.0
Contributor guide
Assessment
This issue has not been assessed yet.