Change dependency direction so lower layer (Data) depends on higher layer (Log project)
In "Log" project create all required types and logic to execute logging, but without dependency on the DbContext, instead create an abstraction for saving data.
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); } }
Then implement database abstraction in "Data" project
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(); } }
So "Logging" doesn't know about existence of "Data" project, but "Data" project implements/depends on "Logging" projects - no circular dependencies.
Now we need to "glue" them together in our main ASP.NET Core project - which can be called "Entry point" project, this "entry point" project knows or depends on all projects involved in the application.
In Startup class
public void ConfigureServices(IServiceCollection services) { services.AddDbContext(<register your DbContext>); services.AddTransient<Logger>(); services.AddTransient<ILoggingDatabase, SqlLoggingDatabase>(); }