I have an Entity Framework application using ASP.NET Identity 2.2 (i.e., my context inherits from IdentityDbContext<T>
and I have a User
class that inherits from IdentityUser
). I am successfully seeding the AspNetUsers
table using the following calls in my seed method:
var testUser = new User() {
UserName = "TestUser",
Email = "[email protected]"
};
manager.Create(testUser, "TestPassword");
I have extended the model to include a Post
class which includes a reference to my User
class:
public class Post {
public Post() {}
[Required]
public int Id { get; set; }
[Required]
public User User { get; set; }
}
And, of course, this corresponds to the following in my User
class:
public class User : IdentityUser {
public User() : base() {
this.Posts = new HashSet<Post>();
}
public ICollection<Post> Posts { get; set; }
//Additional members...
}
I am then seeding the Posts
collection with the following:
var testPost = new Post() { Id = 1, User = testUser };
context.Posts.AddOrUpdate(
post => post.Id,
testPost
);
Technically, this works fine; the Post
instance is created, and the automatically generated User_Id
field is correctly populated with the Id
of the newly created User
instance.
So what's the problem? Every time it runs, I get the following in my EntityValidationErrors
: "The User field is required". It doesn't prevent my application from working, but it makes it difficult to detect legitimate errors.
Obviously, I could add custom code to my DbContext.SaveChanges()
method in order to ignore this error, but I'd rather understand why it's happening in the first place, particularly if there's a problem with how I'm seeding my data.
It seems that when the UserManager.Create()
method is called, it doesn't update the User
instance with the information needed to create a reference. My assumption is that it's not populating the Id
field, but I haven't confirmed.
Regardless, the solution is to reload the user after the call to UserManager.Create()
. My final code looks something like:
var manager = new UserManager<User>(new UserStore<User>(context));
var testUser = new User() {
UserName = "TestUser",
Email = "[email protected]"
};
if (manager.Users.Count<User>() == 0) {
manager.Create(testUser, "TestPassword");
}
testUser = (User)manager
.Users
.Where<User>(u => u.UserName == "TestUser")
.FirstOrDefault<User>();
I was then able to seed the Post
record the same way as before:
var testPost = new Post() { Id = 1, User = testUser };
context.Posts.AddOrUpdate(
post => post.Id,
testPost
);
Note: If using a
[ForeignKey]
attribute, it is apparently necessary to assign theUser
byId
(e.g.,UserId = testUser.Id
) instead of by object reference (e.g.,User = testUser
).
In my actual application this is all shuffled off to a CreateUser()
helper method so it's easy to create multiple test users, but this covers the basics. This also addresses a flaw in my original code in that I wasn't previously checking to determine if the user had already been created or not.