Доступ к сервисам из DbContext в .Net Core.2,1 - PullRequest
0 голосов
/ 21 февраля 2019

У меня есть проект .Net Core 2.1 Web Api.Я создаю базу DbContext, имя которой DataContext.cs.Я хочу начать DataContext с IAuditHelper.При запуске проекта я могу установить AuditHelper из моего Startup.cs .

Но после запуска проекта и выполнения метода SaveChangesAsync, равен нулю. Как можно получить AuditHelper из My DataContext?( Я знаю, что если я добавлю IAuditHelper в свой конструктор DataContext, я могу его взять. Но в этой ситуации 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 голосов
/ 21 февраля 2019

Внедрение зависимостей 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)
    {
    }
}

. Я не совсем понимаю, зачем вам нужен AuditHelper в интерфейсе IDataContext, ясохранит его в приватном файле в 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>();

        ...
    }

    ...
}

Вы можетенайти разницу между областями в ссылка .

Контроллер:

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);
    }

И причина соединения должна быть в конфигурации, см. Учебник .

...