我有.Net Core 2.1 Web Api项目。我创建基础DbContext,名称为DataContext.cs
。我想从DataContext
开始IAuditHelper
。项目启动时,我可以在 Startup.cs 中设置AuditHelper
。
但是,在项目启动并执行SaveChangesAsync
方法之后,它为空。。如何从我的DataContext中获取AuditHelper? (我知道,如果我在DataContext构造函数中注入IAuditHelper,那么我可以接受。但是,在这种情况下,Datacontext希望在任何地方都可以使用IAuditHelper。)
DataContext.cs
public class DataContext : DbContext,IDataContext
{
public IAuditHelper AuditHelper { get; set; }
public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = default(CancellationToken))
{
auditHelper.LogMyChangesToDatabase()
return (await base.SaveChangesAsync(true, cancellationToken));
}
}
IDataContext.cs
public interface IDataContext : IDisposable
{
IAuditHelper AuditHelper{ get; set; }
Task<int> SaveChangesAsync(CancellationToken cancellationToken);
Task<int> SaveChangesWithoutAuditAsync(CancellationToken cancellationToken);
}
UniversityDbContext.cs
public class UniversityDbContext: DataContext
{
override protected void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer("server=.; database=.; user id=.;
password=.;");
}
public UniversityDbContext() : base()
{
}
}
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddScoped<IAuditHelper, AuditHelper>();
services.AddScoped<IDataContext, DataContext>();
services.AddScoped<DataContext, UniversityDbContext>();
services.AddDbContext<UniversityDbContext>();
var sp = services.BuildServiceProvider();
var dataContext = sp.GetService<IDataContext>();
dataContext.AuditHelper = sp.GetService<IAuditHelper>();
}
答案 0 :(得分:1)
ASP.NET Core依赖项注入不支持属性注入,您可以改为将依赖项注入到构造函数中,如下所示。另一种选择是使用支持属性注入的容器,例如Unity或Autofac。
public class DataContext : DbContext, IDataContext
{
public DataContext(IAuditHelper auditHelper, DbContextOptions options)
: base(options)
{
AuditHelper = auditHelper;
}
public IAuditHelper AuditHelper { get; private set; }
public override Task<int> SaveChangesAsync(CancellationToken cancellationToken = default(CancellationToken))
{
AuditHelper.LogMyChangesToDatabase();
return base.SaveChangesAsync(true, cancellationToken);
}
...
}
public interface IDataContext : IDisposable
{
IAuditHelper AuditHelper { get; }
Task<int> SaveChangesAsync(CancellationToken cancellationToken);
...
}
public class UniversityDbContext : DataContext
{
public UniversityDbContext(IAuditHelper auditHelper, DbContextOptions options)
: base(auditHelper, options)
{
}
}
我不太了解为什么需要在IDataContext接口中使用AuditHelper,我会将其保存在DataContext中的私有文件中,而不会公开。
AuditHelper类:
public class AuditHelper : IAuditHelper
{
private readonly IHttpContextAccessor _httpContextAccessor;
public AuditHelper(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
public void LogMyChangesToDatabase()
{
//_httpContextAccessor.HttpContext.
}
}
在“启动”类中:
public class Startup
{
...
public void ConfigureServices(IServiceCollection services)
{
...
services.AddHttpContextAccessor();
services.AddDbContext<UniversityDbContext>(options
=> options.UseSqlServer("Server=(localdb)\\mssqllocaldb;Database=TestUniversity;Trusted_Connection=True;MultipleActiveResultSets=true"));
services.AddScoped<IAuditHelper, AuditHelper>();
...
}
...
}
您可以在the link处找到范围之间的差异。
控制器:
public class SomeController : ControllerBase
{
private readonly UniversityDbContext _context;
public SomeController(UniversityDbContext context)
{
_context = context;
}
[HttpPost]
public async Task Post([FromBody] string value)
{
...
await _context.SaveChangesAsync();
}
}
我还建议遵循TAP并更改LogMyChangesToDatabase:
public async Task LogMyChangesToDatabase()
{
//_httpContextAccessor.HttpContext.
//await
}
SaveChangesAsync将相应地为:
public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = default(CancellationToken))
{
await AuditHelper.LogMyChangesToDatabase();
return await base.SaveChangesAsync(true, cancellationToken);
}
原因连接字符串应位于配置see tutorial中。