我正在使用时间戳列来检查我的实体中的并发性。当 2 个不同上下文中的数据不相同时,会正确抛出异常。
当保存的时候出现这样的异常,我调用下面的方法来处理:
public static void HandleOptimisticConcurrencyException(ObjectContext context, OptimisticConcurrencyException ex)
{
string msg = @"The data has changed while you were editing it.
If you save, your changes will override the previous ones.
If you don't, your changes will be lost.
Do you want to save your changes ?";
var ret = System.Windows.MessageBox.Show(msg, "Concurrency error...", MessageBoxButton.YesNo, MessageBoxImage.Warning);
if (ret == MessageBoxResult.Yes)
{
if (ex.StateEntries != null)
{
foreach (var item in ex.StateEntries)
{
context.Refresh(RefreshMode.ClientWins, item.Entity);
}
}
}
else
{
if (ex.StateEntries != null)
{
foreach (var item in ex.StateEntries)
{
context.Refresh(RefreshMode.StoreWins, item.Entity);
}
}
}
context.SaveChanges();
}
我检查了,刷新是在每个故障实体上执行的。但是,第二个SaveChanges()
总是重新抛出一个OptimisticConcurrencyException
.
难道我做错了什么 ?
提前致谢
编辑
我注意到问题是由于第一次之前的方法调用而出现的SaveChanges()
try
{
this.UpdateFlags();
this.repository.Context.SaveChanges();
}
catch (OptimisticConcurrencyException ex)
{
ExceptionHelpers.HandleOptimisticConcurrencyException(this.repository.Context, ex);
}
如果我注释掉UpdateFlags()
电话,我没有问题。
这是此方法的代码:
private void UpdateFlags()
{
DateTime now = DateTime.Now;
int masterId = (int)this.navigationContext.Item;
var master = this.repository.Context.Masters.Where(e => e.Id == masterId).FirstOrDefault();
foreach (var project in master.Projects)
{
// update flags for each project.
if (project.Dashboard == null)
{
project.Dashboard = new Dashboard();
}
var flags = project.Dashboard;
flags.ModifiedOn = now;
// Update DP flags
var dpFlag = (int)project.Tasks.Where(e => e.TaskDP != null)
.Select(e => this.CalculateCompletionStatus(e, now))
.DefaultIfEmpty(CompletionStatusType.Ok)
.Max();
flags.DP = dpFlag;
// Update TRS flags
var trsFlag = (int)project.Tasks.Where(e => e.TaskTRSs != null)
.Select(e => this.CalculateCompletionStatus(e, now))
.DefaultIfEmpty(CompletionStatusType.Ok)
.Max();
flags.TRS = trsFlag;
// Update REV flags
var revFlag = (int)project.Tasks.Where(e => e.TaskREV != null)
.Select(e => this.CalculateCompletionStatus(e, now))
.DefaultIfEmpty(CompletionStatusType.Ok)
.Max();
flags.REV = revFlag;
// Update DTP flags
var dtpFlag = (int)project.Tasks.Where(e => e.TaskDTP != null)
.Select(e => this.CalculateCompletionStatus(e, now))
.DefaultIfEmpty(CompletionStatusType.Ok)
.Max();
flags.DTP = dtpFlag;
// Update DEL flags
var delFlag = (int)project.Tasks.Where(e => e.TaskDEL != null)
.Select(e => this.CalculateCompletionStatus(e, now))
.DefaultIfEmpty(CompletionStatusType.Ok)
.Max();
flags.DEL = delFlag;
// Update FIN Flag
var finFlag = (int)project.SalesTasks.Select(e => this.CalculateCompletionStatus(e, now))
.DefaultIfEmpty(CompletionStatusType.Ok)
.Max();
flags.FIN = finFlag;
// Update Project flag
if (flags.REV == (int)CompletionStatusType.Client && project.DTPBeforeReview.HasValue && project.DTPBeforeReview.Value == false)
{
// Corner case : Review is late because of an external person (= grey) and DTP Before REV is not set
// => all moments after REV are not taken in account.
var projFlag = new List<int> { dpFlag, trsFlag, revFlag }.Max();
flags.ProjectStatus = projFlag;
}
else
{
var projFlag = new List<int> { dpFlag, trsFlag, revFlag, dtpFlag, delFlag, finFlag }.Max();
flags.ProjectStatus = projFlag;
}
}
}
但是我看不出问题出在哪里,因为这是在第一次之前完成的SaveChanges()