'EntityFramework Core - ValueObject and SQLite ShadowID exception

I'm currently using ValueObjects for the first time and I'm struggling with using them right away in my testing setup.

Current situation

I have a DbContext for testing targeting SQLite with the migrations for SQLite. My ValueObject looks like this:

public class TimeSlot : ValueObject
    {
        public int Day { get; private set; }
        public int FromHour { get; private set; }
        public int ToHour { get; private set; }

        public TimeSlot(int day, int fromHour, int toHour)
        {
            Day = day;
            FromHour = fromHour;
            ToHour = toHour;
        }

        public TimeSlot()
        {
            
        }

        protected override IEnumerable<object> GetEqualityComponents()
        {
            yield return Day;
            yield return FromHour;
            yield return ToHour;
        }
    }

The entity configuration for the DbSet that contains the TimeSlot-ValueObject looks like this:

public class GlobalSettingConfiguration : IEntityTypeConfiguration<GlobalSetting>
    {
        public void Configure(EntityTypeBuilder<GlobalSetting> builder)
        {
            builder.ToTable("GlobalSettingsEF");
            builder.HasKey(x => x.GlobalSettingId);

            builder.OwnsMany(x => x.TimeSlots);
        }
    }

The migration for this looks as follows:

migrationBuilder.CreateTable(
                name: "TimeSlot",
                columns: table => new
                {
                    GlobalSettingId = table.Column<Guid>(type: "TEXT", nullable: false),
                    Id = table.Column<int>(type: "INTEGER", nullable: false),
                    Day = table.Column<int>(type: "INTEGER", nullable: false),
                    FromHour = table.Column<int>(type: "INTEGER", nullable: false),
                    ToHour = table.Column<int>(type: "INTEGER", nullable: false)
                },
                constraints: table =>
                {
                    table.PrimaryKey("PK_TimeSlot", x => new { x.GlobalSettingId, x.Id });
                    table.ForeignKey(
                        name: "FK_TimeSlot_GlobalSettings_GlobalSettingId",
                        column: x => x.GlobalSettingId,
                        principalTable: "GlobalSettings",
                        principalColumn: "GlobalSettingId",
                        onDelete: ReferentialAction.Cascade);
                });

In my test I create dummy entries for the TimeSlot-Collection in the GlobalSetting (I'm using the DTO here, as this is the thing that get's thrown in by the user):

public static List<TimeSlotDto> GetDummyTimeSlots()
        {
            var timeSlots = new List<TimeSlotDto>();

            for (int day = 1; day < 3; day++)
            {
                var tempTimeSlot = new TimeSlotDto
                {
                    Day = day,
                    FromHour = 7 + day,
                    ToHour = 14 + day
                };

                timeSlots.Add(tempTimeSlot);
            }

            return timeSlots;
        }

Error

On my await _dbContext.SaveChangesAsync()-call I get the following exception:

Microsoft.EntityFrameworkCore.DbUpdateException : An error occurred while updating the entries. See the inner exception for details.
  ----> Microsoft.Data.Sqlite.SqliteException : SQLite Error 19: 'NOT NULL constraint failed: TimeSlot.Id'.

Question

What am I doing wrong here? As I understood it, the shadow-Id should not be assigned to anything by me, instead EFCore will do this automatically.



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source