从.Net Core中的DbContext访问服务。 2.1

时间:2019-02-21 13:13:41

标签: c# asp.net-core-2.1 asp.net-core-webapi-2.1

我有.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>();
}

1 个答案:

答案 0 :(得分:1)

ASP.NET Core依赖项注入不支持属性注入,您可以改为将依赖项注入到构造函数中,如下所示。另一种选择是使用支持属性注入的容器,例如UnityAutofac

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中。