【问题标题】:How do I seed IdentityUser references in an Entity Framework application?如何在实体框架应用程序中播种 IdentityUser 引用?
【发布时间】:2015-04-30 23:25:09
【问题描述】:

我有一个使用 ASP.NET Identity 2.2 的实体框架应用程序(即,我的上下文继承自 IdentityDbContext<T>,我有一个继承自 IdentityUserUser 类)。我在种子方法中使用以下调用成功地为AspNetUsers 表播种:

var testUser = new User() {
  UserName = "TestUser",
  Email = "TestUser@Domain.tld"
};

manager.Create(testUser, "TestPassword");

我已扩展模型以包含一个 Post 类,其中包含对我的 User 类的引用:

public class Post {

  public Post() {}

  [Required]
  public int Id { get; set; }

  [Required]
  public User User { get; set; }

}

当然,这对应于我的User 类中的以下内容:

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 中得到以下信息:“用户字段是必需的”。它不会阻止我的应用程序正常工作,但它会使检测合法错误变得困难。

显然,我可以将自定义代码添加到我的 DbContext.SaveChanges() 方法中以忽略此错误,但我宁愿首先了解它为什么会发生,特别是如果我的数据播种方式存在问题.

【问题讨论】:

  • 如果您首先插入用户,调用 SaveChanges(),然后使用另一个 SaveChanges() 插入帖子,是否还会出现此错误?
  • @JeroenVannevel - 这不起作用,但我确实找到了解决方案(并且即将发布答案)。

标签: c# asp.net entity-framework entity-framework-6 asp.net-identity-2


【解决方案1】:

似乎在调用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
);    

注意: 如果使用[ForeignKey] 属性,显然有必要通过Id(例如UserId = testUser.Id)而不是通过对象引用(例如@ 987654333@)。

在我的实际应用程序中,这一切都被改组为 CreateUser() 辅助方法,因此创建多个测试用户很容易,但这涵盖了基础知识。这也解决了我的原始代码中的一个缺陷,即我之前没有检查以确定用户是否已经创建。

【讨论】:

  • 关于冰淇淋评论,用户的名字出现在这里gelato.network/about 并且他们在网络上(在 ethereum.se)上发布了另一个帖子来推广该产品。顺便说一句,我不希望直接在用户的帖子上进行此类讨论。随意在我潜伏的聊天室中联系我,或在我的旧答案之一下发表评论,就像我刚刚对你的答案所做的那样。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-04-03
  • 1970-01-01
  • 2020-09-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多