如何在 Entity Framework 应用程序中植入 IdentityUser 引用?
How do I seed IdentityUser references in an Entity Framework application?
我有一个使用 ASP.NET Identity 2.2 的 Entity Framework 应用程序(即,我的上下文继承自 IdentityDbContext<T>
并且我有一个 User
class 继承来自 IdentityUser
)。我在我的种子方法中使用以下调用成功地为 AspNetUsers
table 播种:
var testUser = new User() {
UserName = "TestUser",
Email = "TestUser@Domain.tld"
};
manager.Create(testUser, "TestPassword");
我已扩展模型以包含 Post
class,其中包含对我的 User
class:
的引用
public class Post {
public Post() {}
[Required]
public int Id { get; set; }
[Required]
public User User { get; set; }
}
当然,这对应于我的 User
class 中的以下内容:
public class User : IdentityUser {
public User() : base() {
this.Posts = new HashSet<Post>();
}
public ICollection<Post> Posts { get; set; }
//Additional members...
}
然后我在 Posts
集合中播种以下内容:
var testPost = new Post() { Id = 1, User = testUser };
context.Posts.AddOrUpdate(
post => post.Id,
testPost
);
从技术上讲,这工作正常; Post
实例已创建,自动生成的 User_Id
字段已正确填充新创建的 User
实例的 Id
。
所以问题是什么?每次运行时,我都会在 EntityValidationErrors
中得到以下内容:"The User field is required"。它不会阻止我的应用程序正常工作,但会增加检测合法错误的难度。
显然,我可以将自定义代码添加到我的 DbContext.SaveChanges()
方法中以忽略此错误,但我宁愿首先理解为什么会发生这种情况,尤其是当我的操作方式出现问题时我正在播种我的数据。
似乎在调用 UserManager.Create()
方法时,它不会使用创建引用所需的信息更新 User
实例。我的假设是它没有填充 Id
字段,但我还没有确认。
无论如何,解决方案是在调用 UserManager.Create()
后重新加载用户。我的最终代码类似于:
var manager = new UserManager<User>(new UserStore<User>(context));
var testUser = new User() {
UserName = "TestUser",
Email = "TestUser@Domain.tld"
};
if (manager.Users.Count<User>() == 0) {
manager.Create(testUser, "TestPassword");
}
testUser = (User)manager
.Users
.Where<User>(u => u.UserName == "TestUser")
.FirstOrDefault<User>();
然后我可以像以前一样为 Post
记录播种:
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 the User
by Id
(e.g., UserId = testUser.Id
) instead of by object reference (e.g., User = testUser
).
在我的实际应用程序中,这一切都被改组为 CreateUser()
辅助方法,因此很容易创建多个测试用户,但这涵盖了基础知识。这也解决了我原始代码中的一个缺陷,因为我之前没有检查以确定用户是否已经创建。
我有一个使用 ASP.NET Identity 2.2 的 Entity Framework 应用程序(即,我的上下文继承自 IdentityDbContext<T>
并且我有一个 User
class 继承来自 IdentityUser
)。我在我的种子方法中使用以下调用成功地为 AspNetUsers
table 播种:
var testUser = new User() {
UserName = "TestUser",
Email = "TestUser@Domain.tld"
};
manager.Create(testUser, "TestPassword");
我已扩展模型以包含 Post
class,其中包含对我的 User
class:
public class Post {
public Post() {}
[Required]
public int Id { get; set; }
[Required]
public User User { get; set; }
}
当然,这对应于我的 User
class 中的以下内容:
public class User : IdentityUser {
public User() : base() {
this.Posts = new HashSet<Post>();
}
public ICollection<Post> Posts { get; set; }
//Additional members...
}
然后我在 Posts
集合中播种以下内容:
var testPost = new Post() { Id = 1, User = testUser };
context.Posts.AddOrUpdate(
post => post.Id,
testPost
);
从技术上讲,这工作正常; Post
实例已创建,自动生成的 User_Id
字段已正确填充新创建的 User
实例的 Id
。
所以问题是什么?每次运行时,我都会在 EntityValidationErrors
中得到以下内容:"The User field is required"。它不会阻止我的应用程序正常工作,但会增加检测合法错误的难度。
显然,我可以将自定义代码添加到我的 DbContext.SaveChanges()
方法中以忽略此错误,但我宁愿首先理解为什么会发生这种情况,尤其是当我的操作方式出现问题时我正在播种我的数据。
似乎在调用 UserManager.Create()
方法时,它不会使用创建引用所需的信息更新 User
实例。我的假设是它没有填充 Id
字段,但我还没有确认。
无论如何,解决方案是在调用 UserManager.Create()
后重新加载用户。我的最终代码类似于:
var manager = new UserManager<User>(new UserStore<User>(context));
var testUser = new User() {
UserName = "TestUser",
Email = "TestUser@Domain.tld"
};
if (manager.Users.Count<User>() == 0) {
manager.Create(testUser, "TestPassword");
}
testUser = (User)manager
.Users
.Where<User>(u => u.UserName == "TestUser")
.FirstOrDefault<User>();
然后我可以像以前一样为 Post
记录播种:
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
).
在我的实际应用程序中,这一切都被改组为 CreateUser()
辅助方法,因此很容易创建多个测试用户,但这涵盖了基础知识。这也解决了我原始代码中的一个缺陷,因为我之前没有检查以确定用户是否已经创建。