別のボックスでSQLサーバーに接続するEntityFrameworkアプリケーションがあります。プログラムフローは、次の2つの状態に分類できます。
- SimpleInjectorDIフレームワークを使用してコンポジションルートとレジスタタイプを初期化します
- Initアプリケーション(Entity Frameworkを使用してSQLデータベースで読み取りと書き込みを行います)
- タイマーに基づいて、タスク関数は実行予定のコマンドのインスタンスを取得します
ICommandHandler<CommandType>
(コマンドタイプは異なります) Handle(commandType)
このインスタンスを呼び出してコマンドを実行します- 手順3に戻ります
SQLサーバーへの接続が失われた場合にプログラムがクラッシュしないように保護する必要があります。現在、アプリケーションがSQL接続を失うと、未処理の例外がスローされEntityException - The underlying provider failed on Open
ます。
サーバーがオンラインに戻ると、プログラムはリセットして操作を再開できるはずです。
この質問には、アプリケーションのコアであるSimple Injectorの使用が含まれます。初期化されていない状態と実行中の状態の間の状態遷移を記述することについていくつかのアイデアがありますが、最初に、 Simple Injectorの機能-特に私はデコレータに焦点を当てていますが、これが正しいかどうかはわかりません。
他の推奨アーキテクチャを公開し、エラーがより高いレベルでキャッチされて状態の変化が発生する場所からこれがどのように見えるかを確認します。
以下のコード構造
私はコマンド/ハンドラーアプローチを使用しています:
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()
、コマンドを実行できるようになります。
Handle()
Simple Injectorは、プロシージャ呼び出しをラップするために使用できるデコレータを使用できることを確認しました。
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();
}
}