C# 实体框架优化并发异常刷新后重试

C# 实体框架优化并发异常刷新后重试,c#,entity-framework-4,optimistic-concurrency,C#,Entity Framework 4,Optimistic Concurrency,我使用时间戳列来检查实体中的并发性。当两个不同上下文中的数据不相同时,将正确引发异常 当保存时发生这样的异常时,我调用以下方法来处理: public static void HandleOptimisticConcurrencyException(ObjectContext context, OptimisticConcurrencyException ex) { string msg = @"The data has changed while you were editing it.

我使用时间戳列来检查实体中的并发性。当两个不同上下文中的数据不相同时,将正确引发异常

当保存时发生这样的异常时,我调用以下方法来处理:

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()

如果我注释掉
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;
        }
    }
}
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(master.Projects中的var项目)
{
//更新每个项目的标志。
如果(project.Dashboard==null)
{
project.Dashboard=newdashboard();
}
var flags=project.Dashboard;
flags.ModifiedOn=now;
//更新DP标志
var dpFlag=(int)project.Tasks.Where(e=>e.TaskDP!=null)
.Select(e=>this.CalculateCompletionStatus(e,now))
.DefaultIfEmpty(CompletionStatusType.Ok)
.Max();
flags.DP=dpFlag;
//更新TRS标志
var trsFlag=(int)project.Tasks.Where(e=>e.TaskTRSs!=null)
.Select(e=>this.CalculateCompletionStatus(e,now))
.DefaultIfEmpty(CompletionStatusType.Ok)
.Max();
flags.TRS=trsFlag;
//更新版本标志
var revFlag=(int)project.Tasks.Where(e=>e.TaskREV!=null)
.Select(e=>this.CalculateCompletionStatus(e,now))
.DefaultIfEmpty(CompletionStatusType.Ok)
.Max();
flags.REV=revFlag;
//更新DTP标志
var dtpFlag=(int)project.Tasks.Where(e=>e.TaskDTP!=null)
.Select(e=>this.CalculateCompletionStatus(e,now))
.DefaultIfEmpty(CompletionStatusType.Ok)
.Max();
flags.DTP=dtpFlag;
//更新DEL标志
var delFlag=(int)project.Tasks.Where(e=>e.TaskDEL!=null)
.Select(e=>this.CalculateCompletionStatus(e,now))
.DefaultIfEmpty(CompletionStatusType.Ok)
.Max();
flags.DEL=delFlag;
//更新FIN标志
var finFlag=(int)project.salesstasks.Select(e=>this.CalculateCompletionStatus(e,now))
.DefaultIfEmpty(CompletionStatusType.Ok)
.Max();
flags.FIN=finFlag;
//更新项目标志
if(flags.REV==(int)CompletionStatusType.Client&&project.dtpbeforeview.HasValue&&project.dtpbeforeview.Value==false)
{
//角落案例:由于外部人员(=灰色)和未设置修订前的DTP,审查延迟
//=>未考虑转速后的所有瞬间。
var projFlag=新列表{dpFlag,trsFlag,revFlag}.Max();
flags.ProjectStatus=projFlag;
}
其他的
{
var projFlag=新列表{dpFlag,trsFlag,revFlag,dtpFlag,delFlag,finFlag}.Max();
flags.ProjectStatus=projFlag;
}
}
}

但是我不知道问题出在哪里,因为这是在第一次
SaveChanges()

好的,我想我找到了解决方法

问题不是来自导致第一个异常的第一个对象,而是这个对象中更深层次的问题。 为了解决这个问题,我更新了我的方法如下:

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);
            }
        }
    }

    do
    {
        try
        {
            context.SaveChanges();
            break;
        }
        catch (OptimisticConcurrencyException ex2)
        {
            if (ret == MessageBoxResult.Yes)
            {
                foreach (var item in ex2.StateEntries)
                {
                    context.Refresh(RefreshMode.ClientWins, item.Entity);
                }
            }
            else
            {
                foreach (var item in ex2.StateEntries)
                {
                    context.Refresh(RefreshMode.StoreWins, item.Entity);
                }
            }
        }
    }
    while (true);
}

不过,我愿意接受任何其他更好的建议…

感谢您的自我回答,我没有注意到StateEntries是例外情况的一部分,我也不确定我会如何处理。
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);
            }
        }
    }

    do
    {
        try
        {
            context.SaveChanges();
            break;
        }
        catch (OptimisticConcurrencyException ex2)
        {
            if (ret == MessageBoxResult.Yes)
            {
                foreach (var item in ex2.StateEntries)
                {
                    context.Refresh(RefreshMode.ClientWins, item.Entity);
                }
            }
            else
            {
                foreach (var item in ex2.StateEntries)
                {
                    context.Refresh(RefreshMode.StoreWins, item.Entity);
                }
            }
        }
    }
    while (true);
}