Goj*_*tah 20 c# asp.net-mvc entity-framework
我使用内置的身份框架进行用户管理,并希望为AspNetUsers表添加一些自定义.到目前为止,我遇到的每个问题的解决方案都会导致另一个问题.
如果我更改用户模型(例如,通过在AspNetUsers表中添加邮政编码属性和匹配字段),然后调用UserManager.UpdateAsync(用户),它会成功,但不会更新数据库中的邮政编码字段.
至少有一个其他的SO问题试图解决这个问题.但建议修复那里打破其他事情:
1)创建UserDbContext的另一个实例并尝试附加用户对象导致实体框架抱怨"实体对象不能被IEntityChangeTracker的多个实例引用"
2)关闭代理创建摆脱了#1中列出的问题,但导致dbcontext不加载子对象(如AspNetUserLogins,这是非常重要的).
另一种解决方案是访问在Controller中创建的上下文.使用MVC(版本5)模板考虑使用新的ASP .NET Web应用程序的默认AccountController的构造函数方法:
public AccountController()
: this(new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext())))
{
}
public AccountController(UserManager<ApplicationUser> userManager)
{
UserManager = userManager;
}
Run Code Online (Sandbox Code Playgroud)
创建应用程序数据库上下文,但无法通过UserManager访问它(因为UserManager的"存储"私有属性).
这看起来不像是火箭科学,所以我的猜测是我在处理/理解dbcontext生命周期时做了一些基本上错误的事情.
那么:我如何正确访问/使用dbcontext来保存和更新AspNetUsers,关联的自定义属性以及保留子对象(如AspNetUserLogins)?
编辑-------
还有一件事我试过......
我从默认更新了AccountController的构造函数:
public AccountController(UserManager<ApplicationUser> userManager)
{
UserManager = userManager;
}
Run Code Online (Sandbox Code Playgroud)
对此:
public AccountController(UserManager<ApplicationUser> userManager)
{
userDbContext= new UserDbContext();
UserStore<ApplicationUser> store = new UserStore<ApplicationUser>();
UserManager<ApplicationUser> manager = new UserManager<ApplicationUser>(store);
manager.UserValidator = new CustomUserValidator<ApplicationUser>(UserManager);
// UserManager = userManager;
UserManager = manager;
}
Run Code Online (Sandbox Code Playgroud)
试图挂起dbcontext.后来,在公共异步任务方法的主体中,我试图调用:
var updated = await UserManager.UpdateAsync(user);
if (updated.Succeeded)
{
userDbContext.Entry(user).State = System.Data.Entity.EntityState.Modified;
await userDbContext.SaveChangesAsync();
}
Run Code Online (Sandbox Code Playgroud)
但是,更新状态的尝试会引发异常:
"对象层类型'xyz.Models.ApplicationUser'已经生成了代理类型.当AppDomain中的两个或多个不同模型映射相同的对象层类型时,会发生这种情况."
这似乎不正确......它与构造函数中分配的dbcontext相同.
编辑#2 -----
这是ApplicationUser模型:
using Microsoft.AspNet.Identity.EntityFramework;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNet.Identity;
using System.Data.Entity;
namespace xyz.App.Models
{
// You can add profile data for the user by adding more properties to your ApplicationUser class, please visit http://go.microsoft.com/fwlink/?LinkID=317594 to learn more.
public class ApplicationUser : IdentityUser
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string ZipCode { get; set; }
public string PasswordResetToken { get; set; }
public System.DateTime? PasswordResetTokenExpiry { get; set; }
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
// Add custom user claims here
return userIdentity;
}
public ApplicationUser() { }
}
public class UserDbContext : IdentityDbContext<ApplicationUser>
{
public UserDbContext()
: base("DefaultConnection")
{
}
}
}
Run Code Online (Sandbox Code Playgroud)
最终编辑----------------------------
好吧,经过评论中的一些来回,我意识到我是以错误的方式提出问题.我的问题是:如何使用代码优先而不是数据库优先迁移.来自Hibernate学校,我习惯于通过XML或Java中的注释手动将对象映射到表.
因此,在略读这篇文章时,我错过了有关迁移的重要步骤.学过的知识.
Jos*_*osh 33
我遇到了同样的问题.解决这个问题的一个简单方法就是从模型中获取我想要更新的属性,并将它们保存回从UserManager中提取的对象;
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(ApplicationUser model)
{
if (ModelState.IsValid)
{
ApplicationUser u = UserManager.FindById(model.Id);
u.UserName = model.Email;
u.Email = model.Email;
u.StaffName = model.StaffName; // Extra Property
UserManager.Update(u);
return RedirectToAction("Index");
}
return View(model);
}
Run Code Online (Sandbox Code Playgroud)
use*_*388 10
因此,您使用的是数据库优先而不是代码优先.我的建议是使用代码优先.我和你一样,首先开始使用数据库.如果您不使用代码优先,则删除数据库中的迁移表.否则,会引起问题.
如果可能的话,我建议遵循这个代码优先的教程,这对我帮助很大.您可以轻松地将自定义字段添加到您的身份中,并在身份验证过程中与框架完全集成.
归档时间: |
|
查看次数: |
52444 次 |
最近记录: |