Entity framework 4 EF4更新导航属性一个实体对象不能被多个IEntityChangeTracker实例引用
我正在尝试实现一个比方说更改我的帐户电子邮件地址的功能 我想保留R_EmailAddressHistory表中所有用户电子邮件的备份 下面是我的一些项目代码Entity framework 4 EF4更新导航属性一个实体对象不能被多个IEntityChangeTracker实例引用,entity-framework-4,navigation,Entity Framework 4,Navigation,我正在尝试实现一个比方说更改我的帐户电子邮件地址的功能 我想保留R_EmailAddressHistory表中所有用户电子邮件的备份 下面是我的一些项目代码 public bool ChangeEmailAddress(string username, string newEmailAddress, string callbackUrl) { DateTime currentUtcTime = DateTime.UtcNow; R_User currentUser = Use
public bool ChangeEmailAddress(string username, string newEmailAddress, string callbackUrl)
{
DateTime currentUtcTime = DateTime.UtcNow;
R_User currentUser = UserRepo.GetSingle(whereCondition: w=>w.Username == username);
currentUser.UpdateDate = currentUtcTime;
if (currentUser.HasPendingNewEmail)
{
R_EmailAddressHistory currentPendingRequest = EmailHistoRepo.GetSingle(whereCondition: w => w.StatusID == (int)Reno.Common.Enums.RecordStatus.Pending && w.R_User.GId == currentUser.GId);
currentPendingRequest.NewEmail = newEmailAddress;
currentPendingRequest.UpdateDate = currentUtcTime;
EmailHistoRepo.Update(currentPendingRequest);
}
else
{
currentUser.HasPendingNewEmail = true;
R_EmailAddressHistory newEmail = new R_EmailAddressHistory();
newEmail.UserId = currentUser.GId;
newEmail.R_User = currentUser;
newEmail.NewEmail = newEmailAddress;
newEmail.InsertDate = currentUtcTime;
newEmail.StatusID = (int) Reno.Common.Enums.RecordStatus.Pending;
currentUser.R_EmailAddressHistory.Add(newEmail);
}
IdentityResult idtResult = UserRepo.Update(currentUser);
if(idtResult == IdentityResult.Succeeded)
{
//Send notification to current email address for validation before proceeding change email process
bool sendResult = Communication.EmailService.SendChangeEmailValidation(username,currentUser.Email, newEmailAddress, callbackUrl);
return sendResult;
}
else
{
return false;
}
}
前面的方法用于更改电子邮件地址。我的每个表R_User和EmailAddressHistory都有存储库UserRepo和emailhistorrepo。实现相同的IRepositoryBase类,下面是更新方法
public IdentityResult Update(T entity)
{
try
{
if (_currentContext.DbContext.Entry(entity).State == EntityState.Detached)
{
_currentContext.DbContext.Set<T>().Attach(entity);
}
_currentContext.DbContext.Entry(entity).State = EntityState.Modified;
return IdentityResult.Succeeded;
}
catch
{
return IdentityResult.Failed;
}
}
您的当前用户在更新电子邮件地址之前已被修改。首先将更改保存到currentUser 大概是这样的:
R_User currentUser = UserRepo.GetSingle(whereCondition: w=>w.Username == username);
currentUser.UpdateDate = currentUtcTime;
bool pendingNewEmail = currentUser.HasPendingNewEmail;
UserRepo.Update(currentUser);
if (pendingNewEmail)
{
R_EmailAddressHistory currentPendingRequest = EmailHistoRepo.GetSingle(whereCondition: w => w.StatusID == (int)Reno.Common.Enums.RecordStatus.Pending && w.R_User.GId == currentUser.GId);
currentPendingRequest.NewEmail = newEmailAddress;
currentPendingRequest.UpdateDate = currentUtcTime;
EmailHistoRepo.Update(currentPendingRequest);
}
else
我终于找到了答案。问题是当我第一次让用户排队时
R_User currentUser = UserRepo.GetSingle(whereCondition: w=>w.Username == username);
currentUser变量保存其所有R_EmailAddressHistory的引用。
然后,我第二次查询DB以获取挂起的电子邮件更改请求,或者键入R_EmailAddressHistory以修改其新电子邮件及其更新日期,在第行中
R_EmailAddressHistory currentPendingRequest = EmailHistoRepo.GetSingle(whereCondition: w => w.StatusID == (int)Reno.Common.Enums.RecordStatus.Pending && w.R_User.GId == currentUser.GId);
currentPendingRequest.NewEmail = newEmailAddress;
currentPendingRequest.UpdateDate = currentUtcTime;
但te last代码仅更新currentPendingRequest,而currentUser.R_EmailAddressHistory中相同对象的另一个引用未更新,并且已被上下文跟踪。因此,通过对新实例EmailHistorRepo.UpdatecurrentPendingRequest进行更新,代码失败:如果在两个位置引用了相同的对象
因此,解决方案是我唯一修改的:
R_User currentUser = UserRepo.GetSingle(whereCondition: w=>w.Username == username);
currentUser.UpdateDate = currentUtcTime;
if (currentUser.HasPendingNewEmail)
{
R_EmailAddressHistory currentPendingRequest = currentUser.R_EmailAddressHistory.Where(h => h.StatusID == (int)Reno.Common.Enums.RecordStatus.Pending).First(); // EmailHistoRepo.GetSingle(whereCondition: w => w.StatusID == (int)Reno.Common.Enums.RecordStatus.Pending && w.R_User.GId == currentUser.GId);
currentPendingRequest.NewEmail = newEmailAddress;
currentPendingRequest.UpdateDate = currentUtcTime;
}
我决定修改currentUser变量中的实例。旁注:存储库不应返回IdentityResult,它不应以任何方式了解ASP.Net。单一责任原则。谢谢Gert,我会做出改变Hi Leondelaw,问题是我实际上也在使用MVC4和unitoOfWork模式。首次在控制器中查询数据库时,我的UOW是初始化的,它在Global.aspx中的我的应用程序\ EndRequest方法上提交
R_User currentUser = UserRepo.GetSingle(whereCondition: w=>w.Username == username);
currentUser.UpdateDate = currentUtcTime;
if (currentUser.HasPendingNewEmail)
{
R_EmailAddressHistory currentPendingRequest = currentUser.R_EmailAddressHistory.Where(h => h.StatusID == (int)Reno.Common.Enums.RecordStatus.Pending).First(); // EmailHistoRepo.GetSingle(whereCondition: w => w.StatusID == (int)Reno.Common.Enums.RecordStatus.Pending && w.R_User.GId == currentUser.GId);
currentPendingRequest.NewEmail = newEmailAddress;
currentPendingRequest.UpdateDate = currentUtcTime;
}