Search code examples
asp.net-coreentity-framework-core

Default ID value is set into -9223372036854774807 while adding the object


I have an ASP.NET Core 8 project using Entity Framework Core 8.

This is my DbContext:

public class MyDbContext : DbContext
{
    public MyDbContext (DbContextOptions<IguideDbContext> options) : base(options)
    {
    }

    public MyDbContext ()
    {
    }

    public int MyConvertToInt32(long? v)
    {
        return Convert.ToInt32(v);
    }

    public long MyConvertToInt64(int? v)
    {
        return Convert.ToInt64(v);
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        var intToLongConverter = new ValueConverter<long, int>(
            v => MyConvertToInt32(v),
            v => MyConvertToInt64(v));
       
        modelBuilder.Entity<UserModel>()
            .Property(t => t.UserId)
            .HasConversion(intToLongConverter);
       //xxxxxx
    }

    public DbSet<UserModel>? Users { get; set; }
}

This is the UserModel class:

[Table("Users")]
public class UserModel
{
     [Key]
     public long UserId { get; set; }
     public string EmailAddress { get; set; }
     public int  MemberId { get; set; }
     public string Password { get; set; }
}

Here is how I add a new object to the database:

UserModel user = new UserModel();
user.EmailAddress = "aaa";
user.MemberId = 1;
user.Password = "1";

MyDbContext myDbContext = new MyDbContext();
myDbContext.Users.Add(user);

myDbContext.SaveChanges();

While calling myDbContext.SaveChanges();, it throws this error:

Value was either too large or too small for an Int32.

After investigation, I find that this error is thrown while calling MyConvertToInt32 method, because it is trying to convert -9223372036854774807 to int. Is it the value of user.UserId?

It should be 0 because I never assigned a value to it yet. How does this huge -9223372036854774807 value appear?

Note: Here is the workaround I used to resolve the issue. I changed the method with try catch. But I still want to know why there is a huge minus value there.

public int MyConvertToInt32(long? v)
{
    if (v == null)
    {
        return 0;
    }

    int result = 0;

    try
    {
        result = Convert.ToInt32(v);
    }
    catch (Exception e)
    {
        CommonLog.Error(e);
    }

    return result;
}

More Note: After I enable more log for Entity Framework Core with optionsBuilder.EnableSensitiveDataLogging();, I see below useful output. It seems that EF Core indeed assgina big value to the UserId field by default. I don't know why it is designed like this.

dbug: 2024-11-14 14:29:41.949 CoreEventId.StartedTracking[10806] (Microsoft.EntityFrameworkCore.ChangeTracking) Context 'MyDbContext' started tracking 'User' entity with key '{UserId: -9223372036854774807}'


Solution

  • You could check this document:

    Key properties must always have a non-default value when adding a new entity to the context, but some types will be generated by the database. In that case EF will try to generate a temporary value when the entity is added for tracking purposes. After SaveChanges is called the temporary value will be replaced by the value generated by the database.

    If you don't want to generate PK yourself,just use the build-in converter

    modelBuilder.Entity<UserModel>()
        .Property(t => t.UserId)
        .HasConversion<int>();