我有一个带有身份的“相当标准”的实体框架,在其中我为用户地址添加了外键导航属性。当我来更新记录时,地址项将再次添加,并在数据库中添加一个新的自动递增ID。
在这个杰出的论坛的其他地方,我看到它可能是由两个数据库上下文引起的,但我不认为我有这个问题(但也许找不到),并尝试了在那里提出的解决方案: UserManager updating a user record but creating a new record as well。 这里有一些历史,它始于两个数据库上下文,但是我(我想)将它们组合为一个,因为不需要两个。 这是主要的更新功能:(注意:我从另一个SO问题中删除了我尝试的修复程序。)
// POST api/Account/UpdateUserDetail
[Route("UpdateUserDetail")]
public async Task<IHttpActionResult> UpdateUserDetail(SGGUserDTO usertoupdate)
{
//using (SGGContext ctx = new SGGContext())
//{
// ApplicationUserManager UserManager = new ApplicationUserManager(new UserStore<SGGUser>(ctx));
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
string userid = User.Identity.GetUserId(); //Check user is valid
if (usertoupdate.Id != userid)
{
return NotFound();
}
SGGUser user = await UserManager.FindByIdAsync(userid);
if (user == null)
{
return NotFound();
}
Mapper.Map(usertoupdate, user);
var result = await UserManager.UpdateAsync(user);
if (result.Succeeded)
{
return Ok();
}
else
{
return GetErrorResult(result);
}
//}
}
update方法位于API控制器中,其初始化如下所示:
public class AccountController : ApiController
{
private const string LocalLoginProvider = "Local";
private SGGContext db = new SGGContext();
private ApplicationUserManager _userManager;
public AccountController()
{
}
public AccountController(ApplicationUserManager userManager,
ISecureDataFormat<AuthenticationTicket> accessTokenFormat)
{
UserManager = userManager;
AccessTokenFormat = accessTokenFormat;
}
public ApplicationUserManager UserManager
{
get
{
return _userManager ?? Request.GetOwinContext().GetUserManager<ApplicationUserManager>();
}
private set
{
_userManager = value;
}
}
我的身份模型如下:
public class SGGUser : IdentityUser
{
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<SGGUser> manager, string authenticationType = DefaultAuthenticationTypes.ApplicationCookie)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, authenticationType);
// Add custom user claims here
return userIdentity;
}
[Display(Name = "Date of Birth")]
[DataType(DataType.DateTime)]
[DisplayFormat(DataFormatString = "{0:d}",
NullDisplayText = "Please Enter Your Date of Birth",
ApplyFormatInEditMode = true)]
public DateTime? DateOfBirth { get; set; }
public string Title { get; set; }
public string FirstName { get; set; }
.... bunch of stuff
public Address Address { get; set; }
public virtual BusinessUser BusinessUser { get; set; }
public virtual BusinessCustomer BusinessCustomer { get; set; }
.... bunch more stuff
}
ApplicationUserManager是这样的:
public class ApplicationUserManager : UserManager<SGGUser>
{
public ApplicationUserManager(IUserStore<SGGUser> store)
: base(store)
{
}
public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
{
var db = new SGGContext();
var manager = new ApplicationUserManager(new UserStore<SGGUser>(context.Get<SGGContext>()));
// Configure validation logic for usernames
manager.UserValidator = new UserValidator<SGGUser>(manager)
{
AllowOnlyAlphanumericUserNames = false,
RequireUniqueEmail = true
};
// Configure validation logic for passwords
manager.PasswordValidator = new PasswordValidator
{
.... Bunch more stuff
return manager;
}
...,数据库上下文(SGGContext)如下所示:
public class SGGContext : IdentityDbContext<SGGUser>
{
public SGGContext()
: base("SGGContext", throwIfV1Schema: false)
{
}
static SGGContext()
{
Database.SetInitializer(new sggDbInitializer_on_change());
}
public static SGGContext Create()
{
return new SGGContext();
}
public DbSet<Address> Addresses { get; set; }
public DbSet<Business> Businesses { get; set; }
.... bunch more things
}
说实话,我认为所有漂亮的样板东西。
但是当我使用地址更新记录时,用户可以很好地进行更新,但是地址对象添加了一条新记录。 我也确实在此处找到另一篇关于SO的文章:EF record update creates new record for related object 并且我确实尝试使用.Attach,但是由于它引发了错误,我担心我无法使它正常工作。
有人能发现我不经意间有两种情况或发现问题吗? 非常感谢。