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

Make IDbContext #16470

Closed
eltiare opened this issue Jul 5, 2019 · 38 comments
Closed

Make IDbContext #16470

eltiare opened this issue Jul 5, 2019 · 38 comments

Comments

@eltiare
Copy link

eltiare commented Jul 5, 2019

I could not find anything specific to this particular problem. Apologies if this is a dup. I feel an interface for DbContext would be helpful for inheriting context interfaces. Something like this:

    public interface IContext : IDbContext
    {
        DbSet<Review> Reviews { get; }
        DbSet<Location> Locations { get; }
    }

    public class Context : DbContext, IContext
    {
        public DbSet<Review> Reviews { get; set; }
        public DbSet<Location> Locations { get; set; }
        
        public Context(DbContextOptions<Context> options) : base(options)
        {
        }
    }

I'm thinking it might make testing easier because you could drop in anything that conforms to the interface in testing / different environments.

EF Core version: 2.2.4

@ajcvickers
Copy link
Contributor

@eltiare Shipping an interface for DbContext creates problems for evolving the API going forward. Also, we have found that it is often better to use some form of repository pattern if you really want to expose the context services through an interface. That way you control and evolve the interface.

@douglasg14b
Copy link

douglasg14b commented Jul 19, 2019

@ajcvickers

I might be completely missing the idea here, please bear with me:

Shipping an interface for DbContext creates problems for evolving the API going forward.

Can you expand on that? Isn't the interface SUPPOSED to be the API contract? You're not locking anything into the framework, it's enabling the application of dependency inversion as well as interface segregation.

The lack of an IDbContext interface is somewhat breaking to the whole dependency inversion principle? Any interface I make has no equality to what would be IDbContext that allows DbContext to be injected in it's place, I always have to refer back to my concrete implementation of DbContext, which breaks the clean flow of DI in some serious ways.

EF is already a repository pattern, it seems counter-intuitive to force users to implement their own abstraction on top of that if it isn't necessary? Sure, some will want to, but in other cases it's not a necessity. It feels like selecting implementation of principles that Asp.Net Core and other .Net Core projects has been putting to great use.


Example:

Say I have three projects. Following the Clean Architecture, but implementing DDD (Domain Driven Design):

  • Core (lvl 0)
    • Defines interfaces and Dtos
  • Domain (lvl 1)
    • Defined business and domain logic
    • Defines domain entities/models with included business logic
    • Defines concrete Domain Service implementations (That access EF)
  • Infrastructure (lvl 2)
    • Implements concrete classes of interfaces defined in Core
    • Provides DI services and configurations
    • Defines concrete Application Services from interfaces in Core

The reference structure goes Core <- Domain <- Infrastructure.

The necessity to have business logic within domain entities (specifically the aggregate root), puts those into the Domain layer. Which necessitates my IApplicationContext to be defined there as Core cannot reference the layer above it, and EF Core doesn't support using interfaces in the DbSet definition (Who's concrete implementations could be configured via the fluent API), which would be perfect for an interface of 'DbContext'... This is an unfortunate compromise between "Clean Architecture" and DDD purity brought on by the limitations of EF Core.

My Domain Services expect an interface that's equatable to DbContext to be injected, the IApplicationContext. The concrete implementation is provided by the Infrastructure project, but the Domain layer doesn't need to know this, it only needs the contract.

The problem now is IApplicationContext has no equality to DbContext's API. I could add method definitions to my interface from DbContext, but this is just asking for breaking changes in my concrete implementation as soon as any DbContext method signatures change, which would be a non-issue with a contract.


The jist of this is the lack of an abstract API for DbContext necessitates all sorts of unnecessary workarounds as soon as you need strong DI. My example is a flawed one, but I've seen this ran into before in other use cases where strict DI is enforced...

Hopefully you can see how the exclusion of DI-friendliness can quickly cascade into a gigantic host of other problems.

@tb-mtg
Copy link

tb-mtg commented Jul 30, 2019

Shipping an interface for DbContext creates problems for evolving the API going forward.

Everything is evolving isn't it? This should not be a reason to not use Interfaces.

I agree with @eltiare that IDbContext would be helpful.

Even if the API is evolving, simply update the interface if necessary to allow for any evolutions. It will only affect those that are referencing the interface, and they can adjust the code appropriately.

An example could be:

  public interface IDbContext : IDisposable, IInfrastructure<IServiceProvider>, IDbContextDependencies, IDbSetCache, IDbQueryCache, IDbContextPoolable {
    ChangeTracker ChangeTracker { get; }
    DatabaseFacade Database { get; }
    EntityEntry Add(object entity);
    EntityEntry<TEntity> Add<TEntity>(TEntity entity) where TEntity : class;
    Task<EntityEntry> AddAsync(object entity, CancellationToken cancellationToken = default);
    Task<EntityEntry<TEntity>> AddAsync<TEntity>(TEntity entity, CancellationToken cancellationToken = default) where TEntity : class;
    void AddRange(IEnumerable<object> entities);
    void AddRange(params object[] entities);
    Task AddRangeAsync(IEnumerable<object> entities, CancellationToken cancellationToken = default);
    Task AddRangeAsync(params object[] entities);
    EntityEntry<TEntity> Attach<TEntity>(TEntity entity) where TEntity : class;
    EntityEntry Attach(object entity);
    void AttachRange(params object[] entities);
    void AttachRange(IEnumerable<object> entities);
    EntityEntry<TEntity> Entry<TEntity>(TEntity entity) where TEntity : class;
    EntityEntry Entry(object entity);
    bool Equals(object obj);
    object Find(Type entityType, params object[] keyValues);
    TEntity Find<TEntity>(params object[] keyValues) where TEntity : class;
    Task<TEntity> FindAsync<TEntity>(params object[] keyValues) where TEntity : class;
    Task<object> FindAsync(Type entityType, object[] keyValues, CancellationToken cancellationToken);
    Task<TEntity> FindAsync<TEntity>(object[] keyValues, CancellationToken cancellationToken) where TEntity : class;
    Task<object> FindAsync(Type entityType, params object[] keyValues);
    int GetHashCode();
    DbQuery<TQuery> Query<TQuery>() where TQuery : class;
    EntityEntry Remove(object entity);
    EntityEntry<TEntity> Remove<TEntity>(TEntity entity) where TEntity : class;
    void RemoveRange(IEnumerable<object> entities);
    void RemoveRange(params object[] entities);
    int SaveChanges(bool acceptAllChangesOnSuccess);
    int SaveChanges();
    Task<int> SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = default);
    Task<int> SaveChangesAsync(CancellationToken cancellationToken = default);
    DbSet<TEntity> Set<TEntity>() where TEntity : class;
    string ToString();
    EntityEntry Update(object entity);
    EntityEntry<TEntity> Update<TEntity>(TEntity entity) where TEntity : class;
    void UpdateRange(params object[] entities);
    void UpdateRange(IEnumerable<object> entities);
  }

@ajcvickers
Copy link
Contributor

The issue is that adding a new method to an interface breaks any existing implementations of that interface. However, now with interface default methods we may be able to mitigate this in ways that were not possible in the past. Re-opening to consider.

@ajcvickers
Copy link
Contributor

We discussed this in triage and it isn't something we are going to implement, mainly because attempting to create different implementations of the DbContext API (whether for testing or other purposes) is very difficult and tends to lead people down a pit of failure. Also, we don't believe it is bad to have an interface registered in D.I. that your code depends on, but which its implementation depends on an actual DbContext registered in D.I.

@douglasg14b
Copy link

douglasg14b commented May 31, 2020

Revisiting this as this has been a pain for several projects when using DDD now....

@ajcvickers Aren't you and your team completely sidestepping the point of an interface in this context? Asp.net core clearly shows how effectively dependency inversion and inversion of control works. EF Core on the other hand seems to pretend it doesn't exist, and in the process creates a lot of unnecessary headaches.

An IDbContext is not to provide an interface for users to roll their own DbContext, it's to provide an interface so we can effectively utilize DI. How can I have an abstract AppContext that can be referenced by projects BELOW where my AppDbContext is declarted if there is no IDbContext to inherit from for an IAppContext? You can't, an interface cannot inherit from a class.

This also ties into the lack of interfaces for DbSet and the lack of interface configurations for DbSet type parameters (Ie. DbSet<IAuthor>, which is then configured to instantiate/use Author in a configuration).


This breaks IoC, and forces us to adopt awkward, best-practice violating, inconsistent, architectures because EF Core is the odd one out. Unless of course I copy/paste the method & property signatures from DbContext into my own IDbContext. Which now creates a maintenance problem, and should have never been necessary in the first place to support a core tenant of SOLID, a tenant that a sister framework (Asp.Net Core) widely pushes for.

@roji
Copy link
Member

roji commented May 31, 2020

it's to provide an interface so we can effectively utilize DI. How can I have an abstract AppContext that can be referenced by projects BELOW where my AppDbContext is declarted if there is no IDbContext to inherit from for an IAppContext? You can't, an interface cannot inherit from a class.

To understand the request better, are you asking for an interface in order to mock the DbContext for testing purposes? Or is your aim to use IDbContext in your actual product code? If it's the latter, can you provide more details on why you think an interface is needed for that, rather than subclassing DbContext? I'm looking to understand exactly what's blocking you because of the lack of an interface. An interface usually makes more sense where it's reasonable for the implementation to be swapped out for another, which really isn't the case for DbContext.

@alcjamgit
Copy link

alcjamgit commented Jun 23, 2020

@roji I think @douglasg14b clearly states why he wants the interface version - so we can effectively utilize DI, which means ease of testing. Yes an interface makes sense when you need implementations to be swapped out, but not usually. In fact most of the time interfaces are used to make way for testing, why do you think we make interfaces for services every time we use it in a controller or another service, do you think because we plan to swap out the implementation? Of course not, we do it for testing. Dependency injection is a pattern which is clearly promoted by the .Net community and in the case of DbContext there's a clear need for it, yet you seem to be under the impression that @douglasg14b is introducing a new concept.

Also subclassing the DbContext does not solve the issue which is again ease of testing. Yes we can introduce a repository pattern, but there's lot of reasons we don't want to do that - firstly its another abstraction over abstraction and secondly you lose a lot of power and flexibility that your ORM provides.

@roji
Copy link
Member

roji commented Jun 24, 2020

@alcjamgit @douglasg14b we generally don't believe that mocking the DbContext for testing is a successful testing pattern - mainly because it implies mocking LINQ as well (in order to do any operation on that context). We generally recommend either:

  • Mocking at a higher level (i.e. via a repository pattern)
  • Mocking at a lower level (i.e. the InMemory provider, or preferably, Sqlite in-memory mode)
  • Testing against your actual production database real database type (e.g. SQL Server), but not the production instance.

@douglasg14b
Copy link

douglasg14b commented Jun 24, 2020

This isn't necessarily for JUST testing, don't get hungup on individual items. We shouldn't have to enumerate the numerous ways IoC and Dependency Inversion are used in OOP languages. There is literature on those topics spanning back decades, and more recently plenty of guidelines and documentation on how they are effectively implemented and made first-class citizens in .Net Core libraries like Asp.Net Core.

The point is that EF Core prevents effective application of core tenants of SOLID, and it hurts the architecture of many projects, and is in direct conflict with application design guidelines and other libraries.

Emphasis above.


Here is an overly simplified example:

Say your project follows the clean architecture and Domain Driven Design. You have an AppDbContext defined in your Infrastructure layer, you have your domain services & factories in your Domain layer, you have your service interfaces defined in your Core layer.

You need AppDbContext in your Domain layer for your factories. On no, you can't reference Infrastructure because it's in an outer layer, that would cause a circular dependency. How do you solve this? Well, simple, you have an IAppDbContext defined in your Core layer, that is configured in your IoC container, and injected into your domain services, your AppDbContext implements IAppDbContext

But wait. EF Core provides no IDbContext for your IAppDbContext to inherit from, you can't have access to ANY of the DbContext signatures through your injected interface. What now? Well, now you have to tediously copy/paste all the signatures from DbContext into an IDbContext of your own, which is hacky and unnecessary, all so that you can follow an extremely basic example of IoC .

This gets much more complicated when applying DDD and you start considering the lack interface support for DbSet and it's entities, application architecture layers start to get intermingled all because one library (EF Core) is being an outlier as far as DI and IoC goes. However, that DbSet issue is for a different topic, but the point still stands.

See where this is going?

@roji
Copy link
Member

roji commented Jun 24, 2020

@douglasg14b FWIW my response was about testing since this is what @alcjamgit wrote about above.

@douglasg14b I'm not aware of a principle in DI, SOLID or IoC that says that everything must have an interface. Regardless, EF Core is successfully and widely-used in many DI scenarios (e.g. virtually every ASP.NET+EF application). You are typically expected to have your AppDbContext in a relatively low data layer (I guess that would correspond to your Core layer), and reference it from above layers, wherever data operations need to happen.

@alcjamgit
Copy link

@roji, you're typically expected to have AppDbContext in a low data layer, because that's the only option (yes with InMemory Database you can directly use DbContext), but that doesn't mean you can't make it better, does it?

What's your measure of success wide adoption? Yes, wide adoption EF Core has that, that doesn't mean developer experience is great when it comes to DI.

@eltiare
Copy link
Author

eltiare commented Jun 25, 2020

Just in case any newbies stumble across this thread:

Do NOT test against your actual production database. Make a copy if you want real life data and test against that.

@roji
Copy link
Member

roji commented Jun 25, 2020

@eltiare thanks, that was some poor wording on my part 😄 Corrected that comment...

@smitpatel
Copy link
Contributor

If you end up testing against your actual production database, keep a backup job handy.

@zejji
Copy link

zejji commented Sep 30, 2020

+1 for adding an IDbContext

@roji - Say for example we have an app with more than one than one type of concrete DbContext and we want to use DI and/or create methods that operate upon an interface. This may be e.g. to avoid circular references in actual production code (in our case, from using a fork of the DbContextScope library) or to allow for mocking. How can we do that currently? There's no IDbContext that the interfaces can inherit from, so we have to create our own which, as mentioned above, imposes an additional maintenance burden.

@douglasg14b
Copy link

douglasg14b commented Sep 30, 2020

I don't think @roji cares :/ they seemed unwilling to even give the principles that .NET uses as foundations a second thought when it comes to this issue... Which is pretty disappointing coming from a .NET Platform org member.

This issue would be open otherwise, as it's a very valid problem caused by an implementation ignorant of these principles.

Obviously logic and reason won't work here, hopefully more individuals who are adopting these patterns & principles start showing up to complain, maybe that will prompt... something?

@roji
Copy link
Member

roji commented Oct 3, 2020

@zejji and @douglasg14b, I think it's really worth distinguishing between the question of a DbContext interface for testing/mocking purposes, and the question of that interface for actual application use.

For testing (see docs), we do recommend testing against your actual database whenever possible. But when that's not desirable, the recommend way to mock is to use the InMemory database. That functionally gives you a DbContext working against memory data structure, which you can assert against etc. An actual mock of a DbContext for this purpose is a problematic proposal because mocking LINQ can be very difficult, depending on exactly what you're doing. However, having written all that, there's nothing preventing mocking DbContext via subclassing, rather than via an interface, if that's really desired.

Now, regarding a DbContext interface for non-testing purposes...

Say for example we have an app with more than one than one type of concrete DbContext and we want to use DI and/or create methods that operate upon an interface.

I'm not sure I'm following your scenario. If you're proposing to inject actual DbContexts in a non-testing scenario, how do you propose to run queries against those contexts, given that LINQ queries are strongly-typed etc.? What would the shape of IDbContext look like in that scenario?

@douglasg14b I promise you that I do care - but I'm still trying to understand precisely what you find insufficient. Looking at the clean architecture which you linked to above, the "ASP.NET Core Architecture" diagram represents the recommended architecture for an ASP.NET DI application. The EF DbContext is in the Infrastructure layer, the entity POCOs are in Core (which Infrastructure depends on), etc. How is the current EF design not respecting that document?

And as above, what exact API shape would IDbContext have, and how would you use it in a productive way? A code sample of what you're looking for could help clear up the confusion here.

@Rob-Page
Copy link

Rob-Page commented Oct 20, 2020

@roji I have run into a similar issue, and maybe I can help break it down a little better.

When working with the Clean Architecture (I have used this template in the past). You are essentially splitting the Product into consumable loosely coupled projects as follows.

image

In order to avoid a circular dependencies in the csproj configuration:

  • The Application project includes the domain project(this way it can have access to the entities it is manipulating).

  • The Infrastructure project includes the Application project (in order to access the entities it is going to configure when it implements EF).

  • The client layer implements both the Application and the Infrastructure layer( the infrastructure first so that the data access service can be setup and injected into the application layer).

This setup creates an awkward workaround with an interface, because the application layer cannot include the infrastructure layer(this would create a circular dependency) an IApplicationDbContext interface is created to bridge the gap. The interfaces helps infer the available EF service injected from the infrastructure layer. The Application layer cannot include the infrastructure layer in order to extend the context, resulting in the need to hardcode out all of the available context members. While this is doable, the ability to extend out an IDbContext would significantly improve the ability and accuracy of representing EF as a services when direct access to the DbContext is not avalible.

image

Feel free to reference this repo that implements this template.

Files important to this issue:

Also if you would like this issue to be specific to testing, would you like another issue to be created for application use? I think most people are bringing this up here because of the issue title not because of eltiare's original issue (though I think it may come back to the same solution).

@roji
Copy link
Member

roji commented Oct 20, 2020

@Rob-Page thanks for trying to provide more details. I've re-read all the documents and sample, and I'm still struggling to understand the issue:

As I wrote above, the ASP.NET Core Infrastructure part in the clean architecture document places the DbContext in Infrastructure project, and not in the Application project. Is there any reason why EF Core should be present in your Application project, even in the form of an interface? As far as I can tell from the document, the recommendation is to have your entities there, but definitely not your context.

More importantly, seeing your IApplicationDbContext.cs, is there anything stopping you from implementing that in your concrete DbContext implementation? In other words, why is an IDbContext interface needed (which is what this issue is about), and what would its shape even be?

@Rob-Page
Copy link

@roji thank you for your response, upon further investigation and thinking through your comments, I believe that you are correct that this is not really an issue that EF Core can solve. I had knee jerk reaction to extend a an interface in order to easily access all of the methods and properties so that things, "work right." This is what erroneously drove my desire for a DbContext Interface.

In this scenario the complex architectural setup has costs. Your last suggestion of implementing a custom IApplicationDbContext in the DbContext helped flip my brain around enough to see that this is an item that the developer should be maintaining as it is very specific to the application setup and implementation of EF Core.

I am going to test out that and a few more ideas and when I have a more concrete solution for my application I will post an update here so that people that run into this in the future will have a little direction. Thanks again for the suggestions and direction here, and to the whole team that works on EF Core, it is an amazing product!

@ajcvickers
Copy link
Contributor

@Rob-Page Thanks for the additional validation on this concept/design. It's really nice to see some external validation on this thread. :-) Also, thanks for the kind words.

@tomaszzmudzinski
Copy link

@Rob-Page did't you found some clean solution for this? I am refactoring my project to use the same clean architecture as you mentioned and I am having the same problem 🤕

@readonlyden
Copy link

It's an interesting issue. DbSet<T> is actually a repository pattern implementation and DbContext is actually an implementation of the Unit Of Work pattern.

Of course, we can create our own interfaces and implementations, maybe generic ones, but isn't this a violation of the DRY and KISS rules? Because in that we would have two repository patterns, two UoW patterns.

We can think about our UoW/Repositories as adapters to EF core ones, or bridges. It would be great to see an example of how to properly abstract from EF Core(for example, during the implementation of the DDD architecture) and not to reinvent the whole framework.

@ParadiseFallen
Copy link

why its closed if it's very important? rn i have problem with multiple repositories. i cant do multiple inheritance from classes, also dont want to create interface for DbContext that will have all methods that DbContext has

@roji
Copy link
Member

roji commented Oct 7, 2021

@ParadiseFallen please read the discussion above, specifically about mocking vs. production uses; if you have more context or something new to add to the above, please post that and we can discuss.

@ParadiseFallen
Copy link

@roji

interface IDbContext
{
  void SaveChanges();
  //.... etc change tracker and other staff
}
interface IIdentityDbContext<...> : IDbContext
{
  //.... identity staff
}
// comes from package CANT CHANGE!
interface IFileStorageDbContext : IDbContest
{
  DbSet<Files> Files {get;set;}
}
// this one in project
class ApplicationDbContext : IdentityDbContext<...>, IIdentityDbContext<...>,IFileStorageDbContext 
{
    // cuz interface said that you need to impliment it!
    DbSet<Files> Files {get;set;}
    // just a identity db context
}
// comes from package CANT CHANGE!
class FileStorageService
{

  private IFileStorageDbContext Context {get;}
  FileStorageService(IFileStorageDbContext context)=>Context  = context;

  public void Foo()
  {
    Context.Files.Add(...);
    Context.SaveChanges();
  }
}

in that sample you has an repository for files and actuall ApplicationDbContext will impliment it. but there no interfaces in efcore. i can made it with multiple inheritance (BUT there no multiple inheritance)

@ParadiseFallen
Copy link

if c# has multiple inheritance it will be easy to do just

//from nuget package
class FilesDbContext : DbContext
{
  DbSet<Files> Files {get;set;}
}
// from package 
class FileService
{
  [Inject]
  prop FilesDbContext Context;
}
// in project
class ApplicationDbContext: IdentityDbContext<...>, FilesDbContext
{

}

@douglasg14b
Copy link

douglasg14b commented Oct 7, 2021

@ParadiseFallen Honestly I've given up on this item, EF Core seems staunchly opposed to following patterns the wider .Net ecosystem have been increasingly adopting since .Net Core 1 (And even long before that). Especially since it's essentially a sibling project to Asp.Net Core which has laid down great guidelines & patterns for better architecture code bases (eg. native dependency inversion encouragement). EF Core fits into these patterns like a square peg into a round hole.

I've come to terms with accepting that EF Core will push against certain patterns, seemingly without logical reasoning, and will just be that sore-thumb sticking out in DDD-like codebases, with parts of the codebase breaking from the expectations solely for EF core usage. :/

Maybe one day I'll make am more detailed example project highlighting the problem, but that's a lot of effort to be dismissed through a lack of understanding again.


Edit: Also multi-inheritance is something that will probably never happen in C#, that's a mess. Also your use case is kind of outside of the purpose of this discussion, though having a sane interface does open up how we can use EF Core, and lets it slot in much easier depending on the architecture.

@ParadiseFallen
Copy link

ParadiseFallen commented Oct 8, 2021

@douglasg14b multiple inheritance is bad. i just said that that can be solution in c++. also i send example only with interfaces tho its show actuall problem

@ParadiseFallen
Copy link

it will be enough to create an interface for everything to work. we just can't implement it in ef core. this should be done by the efcore guys

@ParadiseFallen
Copy link

@ajcvickers @roji @douglasg14b
I create sample project that show main problem that can be easilly solved by adding IDbContext. And why you need to do it

https://github.com/ParadiseFallen/efcore-IDbContext-Issue

I hope you will understand my bad english. I will be glad to answer your questions

@ajcvickers
Copy link
Contributor

@ParadiseFallen The only thing required to make the code in your project work is to define your own IDbContext interface. For example, put this next to your IDbRepository:

    public interface IDBContext
    {
        Task<int> SaveChangesAsync(CancellationToken cancellationToken = default);
    }

Add any other methods from DbContext that you need in the abstraction.

@ParadiseFallen
Copy link

@ajcvickers then it will be stupid copy / paste. It will be nice to have IDbContext in EFCore by default. Why you dont want to made it? cuz it seems that even i can write that kinda interfaces. I just need that DbContext : IDbContext for making data contracts + abstractions. Also if i need more methods i always need to copy / paste it. This change wont brake anything.

I can write that interfaces and made pull request for them if you dont want to write it.

@ajcvickers
Copy link
Contributor

@ParadiseFallen There is a lot of discussion above covering the reasons why it won't be added to EF Core itself. I don't intend to re-engage on that discussion.

@harshwardhan1024
Copy link

I ran into some similar issue which is why I end up here. Following Clean Architecture, I have these layers

  1. Core: Contains DbContext.
  2. Infrastructure: Has everything provider related. Like DI extension method for registering DbContext with SqlServer, IEntityTypeConfigurations.

I have no problem using DbContext as is in my Core layer for various reasons. I treat DbContext as my Repository implementation and thus Core contains DbContext and any database (provider) related things, I move them into Infrastructure layer.

But I am stuck on a little problem. I have to register IEntityTypeConfiguration classes and the only way I know is to add them inside OnModelCreating method of DbContext. But I cannot do that as Core layer cannot depend on Infrastructure. So, my question is:

  • Is there any way to register these configurations inside AddDbContext extension method?
  • Or do I had to create IDbContext interface and use it inside the core and move the actual implementation inside the Infrastructure layer? (I don't want to do this 😔)

@ajcvickers ajcvickers reopened this Oct 16, 2022
@ajcvickers ajcvickers closed this as not planned Won't fix, can't repro, duplicate, stale Oct 16, 2022
@gsGabriel
Copy link

gsGabriel commented Jul 26, 2023

@ajcvickers
Sorry to raise more questions about this, but I don't think creating my own interface will solve it. I have an example of this, I created my own interface in domain layer and with that I am exposing what I need to make queries and execute commands in the application layer. We know that one way to get performance is using compiled queries, the problem with this is that to use compiled queries I necessarily need the concrete class DbContext, so, e.g. I need to implement a repository pattern to expose compiled queries. Another example is to use the DbContextfactory, the factory takes the DbContext from DI, but only accepts concrete class. Why? if we have an interface that represents the DbContext in DI why not to take the new instance from that?
I don't see that creating an interface is to create my own DbContext, but so that I can use all the benefits of the EF without have dependency with concrete class.

@LassazVegaz
Copy link

Are there any other libraries that allow us to do Dependency Invertion?
Probably without re-creating the Repositories and Unit of Work

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests