冒泡更新并发异常以查看

时间:2018-07-31 19:02:50

标签: c# entity-framework orleans

有什么好方法可以将DbUpdateConcurrencyException气泡从视图中弹出到视图?

我目前正在研究Orlean的原型,该原型具有自定义状态,即我正在使用Entity Framework Core与数据库进行通信,并使用EF Core内置的乐观并发模式来管理并发问题。

我遇到的一个问题是,我想将我的Exception异常从纹理中冒出来,并在视图端不接收它。

我正在尝试完成此操作,因为我想处理一些并发问题,这些并发问题在视图上更为紧迫,以便用户可以决定问题,或者至少可以对问题发出警报。

我在Orlean's Gitter上提出了这个建议,但是并没有从中得到很多想法。

我的更新代码示例:

 public Task UpdateUser(User user)
    {
        //Reason for second try/catch is to bubble the error to controller
        try
        {
            userState = new User
            {
                Username = this.GetPrimaryKeyString(),
                accountType = user.accountType,
                FName = user.FName,
                LName = user.LName,
                RowVersion = user.RowVersion,
                CreatedDate = user.CreatedDate
            };
            UpdateState();
        }
        catch (DbUpdateConcurrencyException ex)
        {
            throw ex;
        }
        return Task.CompletedTask;
    }


 public Task UpdateState()
    {
        using (var context = new OrleansContext())
        {
            context.users.Update(userState);
            try
            {
                context.SaveChanges();
            }
            catch ( DbUpdateConcurrencyException ex)
            {
                var entry = ex.Entries.Single();
                var clientValues = (User)entry.Entity;
                var databaseEntry = entry.GetDatabaseValues();
                //Make sure the row wasn't deleted
                if(databaseEntry != null)
                {
                    var databaseValues = (User)databaseEntry.ToObject();
                    if(clientValues.accountType != databaseValues.accountType)
                    {
                        //Bubble up the exception to controller for proper handling
                        throw ex;
                    }
                    //Update Row Version to allow update
                    userState.RowVersion = databaseValues.RowVersion;
                    context.SaveChanges();
                }                
            }
        }
        return Task.CompletedTask;
    }

我愿意就此提出任何建议,只要它可以使用户收到有关异常的警报,并可以查看其数据和当前数据库值。

2 个答案:

答案 0 :(得分:2)

可能未正确序列化或反序列化异常。造成这种情况的主要原因可能是:

  1. Exception类无法正确实现ISerializable模式。
  2. 客户端上不存在包含Exception类的程序集,因此客户端不了解如何创建Exception类型。

在这种情况下,我倾向于第二个原因,因为大多数(但不是全部!)异常类确实正确实现了ISerializable模式。

在任何一种情况下,您都可以捕获异常并将其转变为通用异常。 您可以使用奥尔良的LogFormatter.PrintException(Exception)方法创建一个辅助方法来将异常格式化为字符串。

public static void ThrowPlainException(Exception e) =>
    throw new Exception(Orleans.Runtime.LogFormatter.PrintException(e));

答案 1 :(得分:0)

我遇到的解决方案是创建一个自定义异常类,该类可序列化地向其中添加数据库值对象,然后将其冒泡至视图。

[Serializable]
public class UpdateException : Exception
{
    public object databaseValues { get; set; }
    public UpdateException(object databaseValues)
    {
        this.databaseValues = databaseValues;
    }
    public UpdateException(string message, object databaseValues) :base(message)
    {
        this.databaseValues = databaseValues;
    }
}