弹出"更新并发异常"以查看



从粒度向视图弹出DbUpdateConcurrentException的好方法是什么?

我目前正在开发一个Orlean的原型,它有一个自定义状态,我使用实体框架核心与DB通信,并使用EF核心中内置的乐观并发模式来管理并发问题。

我遇到的问题是,我想把我的Exception从粒度放大到视图,而在视图端没有收到它。

我之所以尝试实现这一点,是因为我想处理一些对视图更为紧迫的并发问题,以便用户能够做出决定,或者至少提醒用户注意这个问题。

我在奥林的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;
}

我愿意接受任何关于这方面的建议,只要它允许用户收到异常警报,并可以查看他们的数据和当前的DB值。

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

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

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

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

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

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

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

相关内容

  • 没有找到相关文章

最新更新