sjh37 / EntityFramework-Reverse-POCO-Code-First-Generator

EntityFramework Reverse POCO Code First Generator - Beautifully generated code that is fully customisable. This generator creates code as if you reverse engineered a database and lovingly created the code by hand. It is free to academics (you need a .edu or a .ac email address), not free for commercial use. Obtain your licence from
https://www.reversepoco.co.uk/
Other
700 stars 230 forks source link

Customise DBContext from tt file #779

Open MarkLFT opened 1 year ago

MarkLFT commented 1 year ago

I need to Inject a service into my DBContext, is it possible to either modify the constructor, or cause it not to be generated so I can put my own into a partial class?

I prefer to do this without modifying the ttinclude or template files. I was burned before when I modified those, forgot I had modified them, and then chased my arse for a couple of hours until I remembered what I had done and reapplied the changes. So now I keep all changes to the partial files or the database.tt file.

sjh37 commented 1 year ago

Could you make use of?

Settings.DbContextClassModifiers = "public partial";

You still get the default constructors generated, but would allow you to create your own constructor. However, I'm not sure which constructor would get used by IoC.

sjh37 commented 1 year ago

Another thought:

Settings.DbContextBaseClass = "ResortDbContext";

Then create a context base class:

public class ResortDbContext : DbContext
{
    protected IService _service;
    public void ResortDbContext(IService service)
    {
        _service = service;
    }
};

Hmm, this might not work actually. Just thinking out loud.

sjh37 commented 1 year ago

Also set

Settings.AddParameterlessConstructorToDbContext = false;
sjh37 commented 1 year ago

To customise the ctor, you can always edit the template within EF.Reverse.POCO.v3.ttinclude line (for efcore 6) = 22855. What I will do though, is to add the ability to list a set of injected services and have those appear in the ctor. No eta on that though.

sjh37 commented 1 year ago

There should be no need to inject services into the DbContext. Instead, you should have services injected into the classes you create, along with your IMyDbContext type and use them in your class.

What is it you are trying to achieve?

MarkLFT commented 1 year ago

Could you make use of?

Settings.DbContextClassModifiers = "public partial";

You still get the default constructors generated, but would allow you to create your own constructor. However, I'm not sure which constructor would get used by IoC.

We do already use the public partial fo the class, this enables me to put the meat of what I need to do in the partial class.

Unfortunately, we cannot have two constructors with the same signature. So, this would not work.

MarkLFT commented 1 year ago

Also set

Settings.AddParameterlessConstructorToDbContext = false;

We have done this.

MarkLFT commented 1 year ago

To customise the ctor, you can always edit the template within EF.Reverse.POCO.v3.ttinclude line (for efcore 6) = 22855. What I will do though, is to add the ability to list a set of injected services and have those appear in the ctor. No eta on that though.

Was trying to avoid changes to the ttinclude files, got burned before when I forgot I had changed them, and then rolled out an upgrade to ReversePoco and lost my changes. Took me ages to find why this weren't working as expected.

MarkLFT commented 1 year ago

There should be no need to inject services into the DbContext. Instead, you should have services injected into the classes you create, along with your IMyDbContext type and use them in your class.

What is it you are trying to achieve?

We are using an EF Interceptor, to perform pre and post save actions. One of the actions is to save some records to an audit trail. The EF Interceptor requires a DBContext to record the audit entries and report any save errors etc.

As an example take a look at https://github.com/dotnet/EntityFramework.Docs/tree/main/samples/core/Miscellaneous/SaveChangesInterception

However, we are using SQL Server, so I am trying to inject an AuditContext into the AuditingInterceptor instead of a ConnectionString, but as AuditingInterceptor needs to be instantiated in the BlogsContext, I need to define the AuditContext in the BlogsContext also.

Hope that makes sense.

MarkLFT commented 1 year ago

One possible solution is to have the option of not creating a constructor in the Context, like there is the option to Omit the OnConfiguring method.

I could then put our own constructor in the partial class.