ASP.NET Core Entity Framework Coreアプリケーションがあり、自分のカスタムロガーを実装したい。 NLogやSerilogなどのすぐに使えるソリューションを使いたくありません。
新しいクラスライブラリプロジェクト(「ロガー」)をアプリケーションに追加し、ロギングを行うクラスを追加しました。ほとんどの場合、サービスプロバイダーを呼び出してdbコンテキストを取得し、それにログオブジェクトを追加して、変更を保存します。
問題は、私のdbコンテキストがタイプクラスライブラリ( "Data")の別のプロジェクトにあるため、 "Logger"がdbコンテキストクラスを使用するために "Data"を参照することです。ただし、データベースにログを保存できるようにするには、「Log」タイプのdbセットを持つdbコンテキストも必要です。これは循環依存関係を意味します。
この状況を解決するにはどうすればよいですか?
下位層(データ)が上位層(ログプロジェクト)に依存するように依存関係の方向を変更する
「ログ」プロジェクトで、ロギングを実行するために必要なすべてのタイプとロジックを作成しますが、DbContextに依存せず、代わりにデータを保存するための抽象化を作成します。
public class LogItem
{
public Guid Id { get; set; }
public DateTime Time { get; set; }
public string Content { get; set; }
}
public interface ILoggingDatabase
{
Task Save(LogItem item);
}
public class Logger
{
private ILoggingDatabase _database;
public Logger(ILoggingDatabase database)
{
_database = database;
}
public Task Log(string content)
{
var item = new LogItem
{
Time = DateTime.UtcNow,
Content = content
};
return _database.Save(item);
}
}
次に、「データ」プロジェクトにデータベース抽象化を実装します
public class SqlLoggingDatabase : ILoggingDatabase
{
private MyDbContext _context;
public SqlLoggingDatabase(MyDbContext context)
{
_context = context;
}
public async Task Save(LogItem item)
{
context.LogItems.Add(item);
await context.SaveChangesAsync();
}
}
したがって、「ロギング」は「データ」プロジェクトの存在を認識していませんが、「データ」プロジェクトは「ロギング」プロジェクトを実装/依存しています-循環依存はありません。
次に、メインのASP.NET Coreプロジェクトでそれらを「接着」する必要があります。これは「エントリポイント」プロジェクトと呼ぶことができます。この「エントリポイント」プロジェクトは、アプリケーションに関係するすべてのプロジェクトを知っているか、依存します。
スタートアップクラス
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext(<register your DbContext>);
services.AddTransient<Logger>();
services.AddTransient<ILoggingDatabase, SqlLoggingDatabase>();
}