Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Decorating EF Core's DbContext #148

Closed
leoshusar opened this issue Jul 20, 2021 · 4 comments
Closed

Decorating EF Core's DbContext #148

leoshusar opened this issue Jul 20, 2021 · 4 comments
Assignees
Milestone

Comments

@leoshusar
Copy link

Hi!
I am currently trying this library for DB audit logging.
I currently have it working for MongoDB - I am using IMongoRepository here.
But is there any way to decorate EF Core's DbContext too?

I tried this decorator

class AuditLogDbContextDecorator : DbContext
{
    private readonly DbContext _decorated;

    public AuditLogDbContextDecorator(DbContext decorated)
    {
        _decorated = decorated;
    }

    public override int SaveChanges()
    {
        LogChanges();
        return _decorated.SaveChanges();
    }

    private void LogChanges()
    {
        ...
    }
}

and decorated it like this: builder.Services.Decorate(typeof(DbContext), typeof(AuditLogDbContextDecorator));
but this fails with

Scrutor.MissingTypeRegistrationException: 'Could not find any registered services for type 'Microsoft.EntityFrameworkCore.DbContext'.'

When I decorate my context implementation: builder.Services.Decorate(typeof(MyContext), typeof(AuditLogDbContextDecorator));
it works, but then it (probably) deadlocks when I want to retrieve my context either in constructor or by GetService<MyContext>(). No error, no exception, it just hangs. Even Ctrl + C won't stop the app, I have to close it using the stop button in VS.

Do you know what can be causing this? I was thinking about circular dependency, could it be? Is it even possible to decorate partial abstract class like DbContext?

@khellang
Copy link
Owner

Hmm, yeah, that's a tricky one. You're essentially decorating a concrete registration as opposed to an interface registration 🤔

I think what's causing the hang might be the injected DbContext in the decorator.

The rule of thumb should basically be that you should inject the exact same type as you decorate. That means you probably should inject MyContext instead.

I haven't really tried this scenario myself, but I can't see why it shouldn't work 😅

@leoshusar
Copy link
Author

leoshusar commented Jul 21, 2021

If you meant like this:

public class AuditLogDbContextDecorator<TContext> : DbContext where TContext : DbContext
{
    private readonly TContext _decorated;

    public AuditLogDbContextDecorator(TContext decorated)
    {
        _decorated = decorated;
    }
}

and register like this

builder.Services.Decorate(typeof(MyContext), typeof(AuditLogDbContextDecorator<MyContext>));

this doesn't work either :( still hangs

@khellang
Copy link
Owner

Hmm, yeah, that's exactly what I meant 😅 I'm not really sure what's going on. Need to take a look at this and do some debugging...

@khellang khellang self-assigned this Jul 22, 2021
Mariachi1231 pushed a commit to Mariachi1231/Scrutor that referenced this issue Sep 13, 2021
khellang pushed a commit that referenced this issue Jan 28, 2022
@khellang
Copy link
Owner

Closed by #155

@khellang khellang added this to the v4.0.0 milestone Jan 28, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants