我正在使用 CQRS 模式使用 NHibernate 从数据库中获取数据。
这是调用 UpdateProductHandler 的 CommittingTransactionCommandHandler
class CommittingTransactionCommandHandler
{
private readonly ISession session;
private readonly ICommandHandler<TCommand> _inner; //Generic Command Handlers
public CommittingTransactionCommandHandler(ISession session)
{
this.session = session;
}
public async Task Execute(TCommand command)
{
using (var txn = session.BeginTransaction(IsolationLevel.Unspecified))
{
try
{
await _inner.Update(command); // This calls the UpdateProducthandler's Update method
txn.Commit();
}
catch (Exception ex)
{
throw;
}
}
}
}
这是更新的命令处理程序。
class UpdateProductHandler : ICommand
{
private readonly ISession session;
public UpdateProductHandler(ISession session)
{
this.session = session;
}
public async Task Update(int id, ProductIdentity productIdentity)
{
var product = session.Get(id);
product.Update(productIdentity);
}
}
这是 Get 的查询处理程序
class GetProductHandler
{
private readonly ISession session;
public GetProductHandler(ISession session)
{
this.session = session;
}
public async Task<Product> Get(int id)
{
var product = session.Get(id);
if (product == null)
throw new Exception("Entity not found");
return Task.FromResult(product);
}
}
这是 Product 实体的代码
class Product
{
public virtual int Id { get; protected set; }
public virtual string Name { get; protected set; }
public virtual string Description { get; protected set; }
public virtual int? Version { get; protected set; }
public virtual void Update(ProductIdentity productIdentity)
{
Name = productIdentity.Name;
Description = productIdentity.Description;
}
}
流量是
CommittingTransactionCommandHandler是一个通用的命令处理程序。这是从 API 调用的,该 API 在内部调用UpdateProductHandler。事务在此打开并在此提交。
情景是这样的
我使用GetProductHandler从数据库获取产品。(在这种情况下,产品的版本号为 10。)
我正在使用UpdateProductHandler更新产品并提交事务下的会话。(此处产品的版本号为 11)
在更新产品之后,我立即使用GetProductHandler查询同一个产品,并在 UI 的编辑模式下加载它。(但使用 GetProductHandler 获取的 Product 的版本号是 10 而不是 11。)
这是问题所在,上面的GetProductHandler不是从数据库获取最新更新,而是获取对象的先前状态。(使用版本号找到)
现在,如果我尝试更新产品,我会收到过时对象状态异常,因为版本号是 10,这不是产品的最新版本。
我已经尝试过 session.Refresh(product) 但都是徒劳的,因为它会影响其他交易。
我该如何解决这个问题?