EF Core - The value of x is unknown when attempting to save changes seeding data
Asked Answered
S

1

2

I am trying to seeddata into database. It was working okay on .NET5

Model configuration

builder.Entity<User>()
            .HasMany(ur => ur.UserRoles)
            .WithOne(u => u.User)
            .HasForeignKey(ur => ur.UserId)
            .IsRequired();

        builder.Entity<Role>()
            .HasMany(ur => ur.UserRoles)
            .WithOne(u => u.Role)
            .HasForeignKey(ur => ur.RoleId)
            .IsRequired();

Now in .NET6, this is the error message when I try to run seeding/adding data into database.

Error] An exception occurred in the database while saving changes for context type '"API.Data.DataContext"'."\n""System.InvalidOperationException: The value of 'UserRole.UserId' is unknown when attempting to save changes. This is because the property is also part of a foreign key for which the principal entity in the relationship is not known.\n   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.PrepareToSave()\n   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.GetEntriesToSave(Boolean cascadeChanges)\n   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(StateManager stateManager, Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken)\n   at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func`4 operation, Func`4 verifySucceeded, CancellationToken cancellationToken)\n   at Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync(Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken)"

my seeding data function;

private void AddUsers()
    {
        Task.Run(async () =>
        {
            string? path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
            if (!_context.Users.Any())
                {
                    var userData = File.ReadAllText(path + @"/Data/SeedData/users.json");
                    var users = JsonSerializer.Deserialize<List<User>>(userData);
                    if (users == null) return;

                    foreach (var user in users)
                    {
                        user.UserName = user.UserName.ToLower();
                        user.EmailConfirmed = true;
                        user.PhoneNumberConfirmed = true;
                        user.IsActive = true;
            // ***this below createAsync is producing error.***
                        await _userManager.CreateAsync(user, Users.DefaultPassword);
                        await _userManager.AddToRoleAsync(user, Roles.BasicUser);
                    }
                  
                    _logger.LogInformation(_localizer["Seeded Users."]);

                }
        }).GetAwaiter().GetResult();
    }
Sidelong answered 4/7, 2022 at 8:43 Comment(4)
Your question is not clear. What are you trying to do and what's the expected result? Are you trying to migrate your database or insert data into it? Please provide more information.Kesha
@Kesha I updated my question. I just run seeding dataSidelong
Thank you for updating the question, now it's clear. In what line exactly does the error occur? CreateAsync? or AddToRoleAsync?Kesha
@Kesha thank you. CreateAsync causes the error as of now.Sidelong
K
0

I've cloned your repository and tracked down the issue by assigning the _userManager.CreateAsync to a variable.

var result = await _userManager.CreateAsync(user, Users.DefaultPassword);
await _userManager.AddToRoleAsync(user, Roles.BasicUser);

now if you debug the program and inspect the result, you'll see the operation has been failed.

Failed: Invalid Username
Username 'cobb walters' is invalid, can only contain letters or digits.

That's caused by those spaces in your seed data. Your username can not contain spaces in Microsoft Identity. Remove them manually or simply by user.UserName = user.UserName.Replace(" ", "_"); and it'll work as expected.

Kesha answered 17/7, 2022 at 6:54 Comment(5)
I am still cant make it work. can you check my repo: github.com/chhinsras/MiniStarter/tree/fixing-seeding-errorsSidelong
@Sidelong I managed to solve the problem. The users and their roles are successfully seeded in my database, please review the updated answer.Kesha
it was that simple. hahaha. was it becuz .NET6?Sidelong
@Sidelong Yes, simple problems are the hardest ones. I don't know, could you insert usernames with spaces in earlier .NET versions? I think it's always been this way.Kesha
it was seeding in my .NET5 project. I just copied the json. Or, maybe I confused.Sidelong

© 2022 - 2024 — McMap. All rights reserved.