【发布时间】:2016-01-12 16:28:55
【问题描述】:
背景: 我有使用 SimpleInjector 作为 IoC 的 WCF 服务,它为每个 WCF 请求创建 DbContext 实例。
后端本身就是 CQRS。 CommandHandlers 有很多装饰器(验证、授权、日志记录、不同处理程序组的一些通用规则等),其中之一是事务装饰器:
public class TransactionCommandHandlerDecorator<TCommand> : ICommandHandler<TCommand>
where TCommand : ICommand
{
private readonly ICommandHandler<TCommand> _handler;
private readonly IMyDbContext _context;
private readonly IPrincipal _principal;
public TransactionCommandHandlerDecorator(ICommandHandler<TCommand> handler,
IMyDbContext context, IPrincipal principal)
{
_handler = handler;
_context = context;
_principal = principal;
}
void ICommandHandler<TCommand>.Handle(TCommand command)
{
using (var transaction = _context.Database.BeginTransaction())
{
try
{
var user = _context.User.Single(x => x.LoginName == _principal.Identity.Name);
_handler.Handle(command);
_context.SaveChangesWithinExplicitTransaction(user);
transaction.Commit();
}
catch (Exception ex)
{
transaction.Rollback();
throw;
}
}
}
}
当任何命令尝试在同一个 WCF 请求中链接执行另一个命令时,就会出现问题。 我在这一行遇到了预期的异常:
using (var transaction = _context.Database.BeginTransaction())
因为我的 DbContext 实例已经有一个事务。
有没有办法检查当前交易是否存在?
【问题讨论】:
-
@qujck 看完这篇文章我不明白
IQuery<TResult>和IDataQuery<TResult>有什么区别。两者都返回数据。为什么我们需要第二个接口呢?有例子吗? -
它们都返回数据,但这些不同的抽象仅在装饰代码时才重要。您需要一个拥有整个操作的抽象,一个可以用
TransactionDecorator之类的东西包装的抽象。您还有其他较低级别的抽象,可以用与原子操作无关的横切关注点(例如AuthoriseDecorator或LoggingDecorator)进行修饰。 -
@qujck 终于明白了。很好的解决方案,我一定会这样做。谢谢!
标签: c# entity-framework simple-injector