我有一个Entity Framework应用程序连接到单独的框上的SQL服务器。程序流程可以分为两种状态:
ICommandHandler<CommandType>
的命令的实例(命令类型不同)Handle(commandType)
以运行命令我需要保护程序在失去与SQL服务器的连接时崩溃。目前,如果应用程序丢失了SQL连接,则会抛出未处理的异常EntityException - The underlying provider failed on Open
。
一旦服务器重新上线,程序应该能够重置并恢复操作。
这个问题涉及使用Simple Injector,因为它是我的应用程序的核心,我有一些关于在未初始化和运行状态之间编写状态转换的想法,但是我想首先询问应该在哪里捕获错误使用Simple Injector功能的好方法 - 特别是我专注于装饰器,但不确定这是否正确。
可以打开任何其他建议的体系结构,以及如何从更高级别捕获错误的位置查看,以便进行状态更改。
以下代码结构
我正在使用Command / Handler方法:
public interface ICommandHandler<TCommand>
{
void Handle(TCommand command);
}
在应用程序启动时,所有实现ICommandHandler<T>
的类型都已注册:
public static void Bootstrap(Container container)
{
container.RegisterManyForOpenGeneric(
typeof(ICommandHandler<>),
System.AppDomain.CurrentDomain.GetAssemblies());
// bootstrap container
}
我的命令处理程序实现如下:
public class AddBusinessUnitCommand
{
public string Name { get; set; }
public float TimeZone { get; set; }
}
public class BusinessUnitCommandHandlers
: ICommandHandler<AddBusinessUnitCommand>
{
private IBusinessUnitService businessUnitService;
public BusinessUnitCommandHandlers(
IBusinessUnitService businessUnitService)
{
this.businessUnitService = businessUnitService;
}
public void Handle(AddBusinessUnitCommand command)
{
// do something
}
}
然后我可以使用Simple Injector来获取类型的实例,例如ICommandHandler<AddBusinessUnitCommand>
,其中将返回一个实例化的BusinessUnitCommandHandlers
对象,允许我Handle()
命令。
我见过Simple Injector可以使用装饰器,我可以用它来包装Handle()
过程调用。
public class TransactionCommandHandlerDecorator<TCommand>
: ICommandHandler<TCommand>
{
private readonly ICommandHandler<TCommand> handlerToCall;
private readonly IUnitOfWork unitOfWork;
public TransactionCommandHandlerDecorator(
IUnitOfWork unitOfWork,
ICommandHandler<TCommand> decorated)
{
this.handlerToCall = decorated;
this.unitOfWork = unitOfWork;
}
public void Handle(TCommand command)
{
this.handlerToCall.Handle(command);
unitOfWork.Save();
}
}
答案 0 :(得分:1)
我需要保护程序在发生丢失时不会崩溃 连接到SQL服务器。
...应该使用的功能以一种很好的方式捕获错误 简单的注射器 - 特别是我专注于装饰器而不是 确定这是否正确。
使用泛型装饰器装饰ICommandHandler<T>
实现有三个重要原因。首先,它会阻止您在应用程序中使用任何重复的代码,因为装饰器只编写一次,并且包含许多ICommandHandler<T>
实现。其次,您可以更改命令处理程序的行为并添加横切关注点,而无需对这些命令处理程序的使用者进行任何更改。最后,即使代码重用和消费者无知不是问题,如果要添加的行为在逻辑上是命令处理程序的一部分,装饰器仍然是有用的。例如,验证执行的命令。这是消费者可能不应该关心的事情,也是您在调用Handle
期间想要做的事情。
我希望您的“命令处理器”(您的计时器)是一段代码,并且是应用程序基础结构的一部分(甚至可能是组合根的一部分)。由于这只是一段代码,因此没有理由使用装饰器来防止代码重复并添加此崩溃保护,因为装饰器可能也不会赢得你那么多。
我们甚至可以争辩说,甚至可能是这块基础结构代码的责任来进行崩溃保护(而不是命令处理程序的责任),特别是因为那段代码必须执行命令重新安排的事情。 (基于故障类型),或将其置于某种“失败的命令队列”(以允许手动重新运行它们)。也许您的设计可以从使用Circuit Breaker Pattern。
中受益