I'm trying to seed some data into database when I startup the server.
But I get a NullReferenceException
when I'm trying to insert user data.
The exception happens on the line
userManager.CreateAsync(user, "P@ssw0rd");
But I've checked that none of the objects in that line are null.
Please give me some advice, thanks in advance.
Here is the code:
public static async Task SeedUsers(UserManager<AppUser> userManager,
RoleManager<AppRole> roleManager, DataContext context)
{
// only seed user when no data in database
if (await userManager.Users.AnyAsync()) return;
var userData = await File.ReadAllTextAsync("Data/Users.json");
var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true };
var users = JsonSerializer.Deserialize<List<AppUser>>(userData);
var roles = new List<AppRole>
{
new AppRole { Name = "Member" },
new AppRole { Name = "Admin" },
new AppRole { Name = "Moderator" },
};
foreach (var role in roles)
{
await roleManager.CreateAsync(role);
}
int langCount = context.Languages.Count(); // Get the total number of rows in the table
int countryCount = context.Countries.Count();
foreach (var user in users)
{
Random random = new Random();
int randIndex1 = random.Next(0, langCount);
int randIndex2 = random.Next(0, langCount);
int randCountryIndex = random.Next(0, countryCount);
int desiredRowCount = random.Next(1, 5);
var langRows1 = context.Languages
.Skip(randIndex1)
.Take(desiredRowCount)
.ToList();
var langRows2 = context.Languages
.Skip(randIndex2)
.Take(desiredRowCount)
.ToList();
var country = context.Countries
.Skip(randCountryIndex)
.Take(1)
.FirstOrDefault();
user.UserName = user.UserName.ToLower();
// specify utc datetime or it will throw error on postgresSQL
user.Created = DateTime.SpecifyKind(user.Created, DateTimeKind.Utc);
user.LastActive = DateTime.SpecifyKind(user.LastActive, DateTimeKind.Utc);
user.Languages = langRows1;
user.InterestedLanguages = langRows2;
user.CountryId = country.Id;
context.Entry(user).State = EntityState.Added;
await userManager.CreateAsync(user, "P@ssw0rd");
await userManager.AddToRoleAsync(user, "Member");
}
var admin = new AppUser
{
UserName = "admin"
};
await userManager.CreateAsync(admin, "P@ssw0rd");
await userManager.AddToRolesAsync(admin, new[] { "Admin", "Moderator" });
}
Log:
fail: Program[0]
An error occurred during migration
System.NullReferenceException: Object reference not set to an instance of an object.
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.NavigationFixer.InitialFixup(InternalEntityEntry entry, InternalEntityEntry duplicateEntry, Boolean fromQuery)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.NavigationFixer.StateChanged(InternalEntityEntry entry, EntityState oldState, Boolean fromQuery)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntryNotifier.StateChanged(InternalEntityEntry entry, EntityState oldState, Boolean fromQuery)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.FireStateChanged(EntityState oldState)
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, Nullable`1 fallbackState)
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.EntityGraphAttacher.AttachGraph(InternalEntityEntry rootEntry, EntityState targetState, EntityState storeGeneratedWithKeySetTargetState, Boolean forceStateWhenUnknownKey)
at Microsoft.EntityFrameworkCore.DbContext.SetEntityState(InternalEntityEntry entry, EntityState entityState)
at Microsoft.EntityFrameworkCore.DbContext.SetEntityState[TEntity](TEntity entity, EntityState entityState)
at Microsoft.EntityFrameworkCore.DbContext.Add[TEntity](TEntity entity)
at Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore`9.CreateAsync(TUser user, CancellationToken cancellationToken)
at Microsoft.AspNetCore.Identity.UserManager`1.CreateAsync(TUser user)
at Microsoft.AspNetCore.Identity.UserManager`1.CreateAsync(TUser user, String password)
at API.Data.Seed.SeedUsers(UserManager`1 userManager, RoleManager`1 roleManager, DataContext context) in /Users/shaoyulin/SoftwareDev/CsharpProjects/LangEx/API/Data/Seed.cs:line 74
my json looks like this:
[
{
"UserName": "rvasyutichev4",
"Gender": "female",
"DateOfBirth": "1988-09-26",
"KnownAs": "rvasyutichev4",
"Created": "2022-07-17",
"LastActive": "2023-01-02",
"Introduction": "Duis consequat dui nec nisi volutpat eleifend. Donec ut dolor. Morbi vel lectus in quam fringilla rhoncus.",
"CountryId": 79,
"Photo": [
{
"Url": "https://randomuser.me/api/portraits/women/321.jpg",
"IsMain": true
}
]
}
]
and here is the AppUser:
public class AppUser : IdentityUser<int>
{
public DateOnly DateOfBirth { get; set; }
public string? KnownAs { get; set; }
public DateTime Created { get; set; } = DateTime.UtcNow;
public DateTime LastActive { get; set; } = DateTime.UtcNow;
public string? Gender { get; set; }
public string? Introduction { get; set; }
public int CountryId { get; set; }
public Country Country { get; set; }
public List<Language> Languages { get; set; } = new();
public List<Language> InterestedLanguages { get; set; } = new();
public List<Photo> Photos { get; set; } = new();
public List<UserLike> LikedByUsers { get; set; }
public List<UserLike> LikedUsers { get; set; }
public List<Message> MessagesSent { get; set; }
public List<Message> MessagesReceived { get; set; }
public ICollection<AppUserRole> UserRoles { get; set; }
}