はじめに
Visual Studioをインストールして開発しようとすると時間がかかるのでVSCodeでお手軽に
しかし、最新環境では開発していないからHello World動かすだけでもはまるという...
参考サイト
◆.NET ダウンロード (Linux、macOS、Windows)
https://dotnet.microsoft.com/ja-jp/download/dotnet
※【.NET6.0】をクリックして、Windowsのx64をダウンロード
dotnet-sdk-6.0.408-win-x64.exe
※【.NET7.0】をクリックして、Windowsのx64をダウンロード
dotnet-sdk-7.0.203-win-x64.exe
◆C#の拡張機能(ms-dotnettools.csharp)インストール
https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.csharp
> dotnet --version
7.0.203
> dotnet new console --use-program-main --target-framework-override net472
※.cs/.csprojを修正
> dotnet run
Hello, World!
◆ODP.NET+C#でOracleに接続する
https://qiita.com/wakasama_pcmaster/items/a81d131f742f0f6e7104
※とりあえず試すための環境構築ネタ
◆C# コンソール アプリ テンプレートで最上位レベルのステートメントが生成される
https://learn.microsoft.com/ja-jp/dotnet/core/tutorials/top-level-templates
※.NET SDK 6.0.300 以降では、consoleテンプレートにはオプションがあります
--use-program-main
これを使用して、最上位レベルのステートメントを使用せず、
メソッドを持つコンソール プロジェクトを Main 作成します。
◆VSCodeで.NET Frameworkを利用する。-.NET Framework利用のための手続き - Technically Impossible
https://impsbl.hatenablog.jp/entry/VSCodeWithDNFW2
◆[コード]リトライ処理
https://free-creators.com/retry-proc/
※これが一番シンプルだが...
◆C# 再試行パターンを実装する
https://shikaku-sh.hatenablog.com/entry/c-sharp-implements-retry-pattern
※説明~テストまで解説してくれている
◆C#でリトライ処理を共通化してみた
https://qiita.com/t_takahari/items/6367434c3484b29cf14d
◆エラーが起こった時にリトライする を一般化したコードを書いてみる
https://qiita.com/Marimoiro/items/b0282792077ab2966135
◆例外発生時にリトライする
https://blog.xin9le.net/entry/2013/09/08/173009
◆C#でアプリケーション設定を取得・保存する、いくつかの方法
https://seraphy.hatenablog.com/entry/20120708/p1
◆【C# 10.0】ファイル スコープ名前空間 (一斉置換設定)
https://ufcpp.net/blog/2021/11/fix-all-file-scoped-namespace/
※名前空間を namespace N {} からファイル スコープな namespace N; に書き換え
ImplicitUsings を true にして未使用 using になる部分をごっそり削除
※.editorconfig設定で一斉置換可能らしい...
コード
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net472</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.Configuration.ConfigurationManager" Version="7.0.0" />
</ItemGroup>
</Project>
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="MaxRetryCount" value="3" />
<add key="RetrySleepTime" value="5000" />
</appSettings>
</configuration>
namespace RetryOperation {
using System;
using System.Configuration;
public static class RetryHelper
{
// 条件に合う場合は指定回数以内で再試行し、それ以外の場合はエラー処理
public static void RetryIfError(Action onAction, Action<Exception> onError, Func<Exception, bool> retryCondition, uint maxRetryCount)
{
if (onAction == null) throw new ArgumentNullException("onAction");
if (onError == null) throw new ArgumentNullException("onError");
if (retryCondition == null) throw new ArgumentNullException("retryCondition");
RetryHelper.RetryIfErrorCore(onAction, onError, retryCondition, maxRetryCount);
}
// コアロジック
private static void RetryIfErrorCore(Action onAction, Action<Exception> onError, Func<Exception, bool> retryCondition, uint? retryCount)
{
if (onError == null) onError = ex => {};
if (retryCondition == null) retryCondition = ex => true;
int maxRetryCount = int.Parse(ConfigurationManager.AppSettings["MaxRetryCount"]);
int RetrySleepTime = int.Parse(ConfigurationManager.AppSettings["RetrySleepTime"]);
for (var retryNumber = 0; retryNumber < maxRetryCount; retryNumber++)
{
try
{
onAction();
}
catch (Exception ex)
{
if (retryCondition(ex))
{
if (!retryCount.HasValue) continue;
if (count++ < retryCount.Value) continue;
}
onError(ex);
}
}
}
}
}
namespace RetryOperation {
using System;
using System.Runtime.ExceptionServices;
class Program
{
static void Main(string[] args)
{
// ループカウンタ
int retryCount = 0;
RetryHelper.RetryIfError(() =>
{
//--- 失敗したら困る処理
// DB保存メソッド呼び出し(失敗)
System.Threading.Thread.Sleep(3000);
Console.WriteLine("DB保存実行!!{0}回目", ++retryCount);
if(retryCount < 3){
throw new InvalidOperationException();
}
},
exstack =>
{
//--- エラー処理
ExceptionDispatchInfo.Capture(exstack).Throw(); //--- スタックトレース維持
},
ex => ex is InvalidOperationException, //--- 条件
5); //--- 再試行回数
}
}
}