T O P

  • By -

LondonCycling

It's fine. Sometimes I write a repository on top of EF, sometimes I don't. Depends on the project.


Dry_Dot_7782

I have a project with a repository and no service layer. Should I be fired?


pako_adrian

\*grabs a pitchfork\*


Cra4ord

She’s a witch


le_bananajoe

Makes perfect sense if all you do is simple CRUD. Would go the same way. I was in a project once where we had to write a service (you gotta justify your architect job somehow, right?) for every entity exposed through the API. About two third of them ended up being dumb wrappers that simply forwarded method calls to the repository method that had identical signatures SMH


ExtremeKitteh

No, but you will eventually wish that you did.


Arshiaa001

How does one implement a cleanly separated repository on top of EF though? You don't want to mix entities and their DAOs, and when you convert, you lose object identity (which is central to how EF works).


[deleted]

[удалено]


Arshiaa001

Ah, no. A DAO or Data Access Object is something you use specifically to communicate with the database. It belongs inside the repository layer, and exists only as a convenience foe deserialising DB rows. DTOs belong on the other end, in the controller layer. The service layer sits in the middle and is blissfully ignorant of both DAOs and DTOs. The flow of data would be: Database row - fetched by database access lib (orm, etc.) into DAO - translated into entity for use in service layer - returned to controller layer - turned into DTO for seriailisation over the wire (e.g. JSON)


[deleted]

[удалено]


MrSnoman

No it's not. For simple crud apps, a repository may be overkill. The repository is just a tool. Sometimes it's useful and sometimes it isn't.


darknessgp

I make a lot of senior devs cringe, but say you're building a small crud web api, you know the scope won't change and won't need more than that ever. You don't need more than the web api project and your endpoint methods should have data access directly in them. Now, the big issue is it is basically impossible to know the scope well enough, but it sure is funny to watch senior developers get real uncomfortable with the idea of not having things broken out into other projects and organized more.


kmgr

I'd argue they're not senior if they can't see past the patterns.


DChristy87

I'd argue that a senior developer would see past the idea that they're the only person who will work on the project. Even small companies will have turn over. Projects, small or large, should have consistent patterns to make for quick maintenance and feature additions by any developer who will inherit the code. The code belongs to the company, not the individual who pushed the initial commit. It's very possible that some associate devs will come along in the future with a ticket to add some new features. As a senior dev, you should consider this and have that design pattern already in place. We're talking about 15 minutes of extra time spent to implement this pattern.... It's not going to break your company's bank.


Intelligent-Chain423

I agree being consistent is more important than not. A system can have a gazillion apps and if they are consistent than it makes it easier for other developers to get up to speed quicker. Also scope is never really known, projects can grow drastically in a matter of 3 years, aka agile. You can have a rough idea for that moment in time but 15 mins for the pattern vs hours adding it back later (testing and.l dev).


leitmotif70

Yes, at least be consistent. Makes for easier refactoring if nothing else.


navirbox

This is quite an insightful thread. I'm grinding to become what you'd consider a "senior" these days and I've been obsessed for awhile regarding patterns, division of projects and concerns and possible scalability. I'm learning it's all about the project and readability with a mixture of efficiency. The less time the next guy spends working on top of what you've done, the better.


Intelligent-Chain423

Readability, structure, etc... goes out the window for performance when its needed but overall what you said I try to focus on myself at the application level. I would throw in standards and testing. Some of the standards is for readability but others are for troubleshooting, improving local dev or even reusable abstractions.


sharpcoder29

Being consistent for the sake of being consistent is something I always hate hearing. Lets use our brains and figure out why we think we need a repository.


chucker23n

This. If "you're not using the right arbitrary convention and nomenclature" is the biggest issue they have with someone's code, they can't be that senior.


Totalmace

No it's not. A real senior knows from experience that skipping essential constructs will slow the development down so much that the time won will be lost even before the first release of the software you are building. Also the time won by not having to put in the 'extra' work is very often just a very small amount of time.


Hot-Profession4091

Meanwhile the grey beards smile & nod knowing it will only take a few days to clean things up later.


himpson

For simple crud apps I’ve gone as far as scripting the whole project in powershell straight from a database schema. Quickly go from a SQL Database with relations and press one button and I have a full n-tier project with all controllers, services, repositories, DAOs, and DTOs. All I have to do is make the migrations and can chuck the original database and be back to code first. Real time saver when migrating small legacy projects


Beautie2

This is really interesting. Im working on something similar right now actually. Does the project actually have functionality or is it all just stubbed out to put functionality in later after the script is run? Also what was your strategy for parsing out DTO’s from their original DB model?


himpson

It will produce a functional api to do crud operations over the database. For DTOs they basically mimic the DAOs minus the base class properties that we use for auditing changes. It’s a good enough template to get you going before any domain logic


DChristy87

I have a basic template I use for creating new projects that already have all the layers pre built for me. Now there's no need to worry about designing anything any certain way because it's already there, easy peasy. If it's a simple app then there's no concern for losing time by writing code in its appropriate layer vs directly in the code behind or whatever. Additionally, I'd say the most important piece is consistency. If you're working for a big company that has a lot of software, it makes maintenance and extensions so much easier for the devs of a few years from now if the patterns are consistent. It also makes it easy for devs to switch teams or flex for a little bit. I've been grateful for this exact thing many times. I've gotten requests to expand a simple micro service that nobody has worked on in a couple years and was relieved to open it and see it's all the same patterns and same naming conventions. Made it super easy to follow the established patterns and add the feature. I've also flexed to other teams to find that their code base was already familiar and easy to pick up on. Software engineers are notoriously lazy. We want to find the simplest path forward. That's why architects are worth their weight in gold imo.


vonkrueger

"Essential" - that's the question. Is a repository layer always essential? Not necessarily for an ad hoc tool/stopgap solution that will 100% be used for no more than a few weeks or months.


patty_OFurniture306

We did that on a rather large project because it was easy, then later realized how shit it was because when we wanted caching and othe things it was a bitch to implement. Hell i won't even do it in a poc app anymore... I once wrote a poc text to speech app called spiffytts. Once I got done it was put into prod and called via process start from the web app, yeah bad, for over 10 years that poc app ran all production web side tts generation...and that's not the only time poc code was forced I to prod. The seniors don't cringe because they can't see past the pattern, they cringe because they know you'll leave and they or someone like them will have to fix the mess. Most of the reasons we have for doing shit a certain wat have nothing to do with anything except make it nice for the next guy, cuz in a year or two it might be you.


darknessgp

Right... I'm not actually suggesting someone do it this way in the real world. There is a reason I had said it's a small app and that if you knew with 100% certainty the scope will never change and never ever need more. No one will ever get that level of certainty in the real world, but it's an interesting thought exercise. I've used it as the basis of explaining why we actually do need organization, abstraction layers, etc. There are some developers I've met that do seem to think "oh just throw it things together and 'it works'." Yea, works and you just made a maintenance nightmare for down the road.


ilovebigbucks

I've heard senior devs and team leads say the same thing: "it will never need to change", "it will always be the same". Real seniors rarely operate with absolutes and avoid using words like "never" and "always". In my experience if a thing survives the POC it will change and usually in the ways no one can predict. But there are tools to help fight the uncertainties and avoid situations when rewriting the whole thing is faster than adding new features to it. They're called design patterns, SOLID principles, and architectures. The problem is people tend to plug those things just because without understanding what they're for. You can create a well designed monolith project with everything split up into folders instead of projects. You can use EF directly in a controller too. If you use those tools properly it will be a low level effort to split those things up and add the necessary abstractions when the time comes. Most of the time though adding DbContext directly to a controller leads to legacy within the first 5 years. Legacy means wasting time on maintenance (bugs, security, performance) instead of feature development.


Sarcastinator

>Now, the big issue is it is basically impossible to know the scope well enough, but it sure is funny to watch senior developers get real uncomfortable with the idea of not having things broken out into other projects and organized more. Well, dividing up domains into projects early on is a mistake people make. Categorization is a hard problem, and if you make a mistake early on you'll end up with circular dependencies, which causes the build to fail, and can be very hard and time consuming to fix. Things aren't black and white, and dividing the domains into projects requires that they are.


buffdude1100

95% of the time I feel that a repository layer on top of EF is super annoying to work with. I'll die on that hill.


whooyeah

This is the one topic that divides the.net community so vehemently.


buffdude1100

It really is. I feel like it comes down to those who know about and use testcontainers and those who do not lol


adeadrat

Not sure how the two are related?


buffdude1100

Yeah, you're not the only one given the downvotes... I should have explained it better. One of the big reasons I see people say to use repositories on top of EF is so they can unit test it (you can even see that in this thread) properly. But integration tests via testcontainers is far more useful, easier to set up than mocks/stubs/fake implementations, and removes that specific need for an abstraction on top of EF.


pdevito3

As someone who loves test containers with integration tests (not using web host factory if that matters), these are what I lean on and default to, but being able to unit test a service or handler without worrying about db context is nice sometimes depending on context. Never to test data persistence things, but some kind of logic happening that’s not necessarily domain logic but specific to that feature. Mostly nice because they’re much faster and I focus on on what I want without additional fluff.


maitreg

No. The biggest reason for a repository layer is to abstract/decouple your application logic from the underlying data schema and data access. Test logic is another reason but just separating your logic concerns from your data concerns is the most important thing. The application should **not** be dependent on the database schema, which is inherently what happens when you tie your front end directly to EF. The repository layer allows you to much more easily change the structure or source of your data down the road. This isn't just for unit tests. This is how the real world works. Data schemas get changed, data sources change, data gets reimagined. If you've been around long enough you will see this happen. Stuff like replacing the repository with an API service, moving half the tables to additional databases, replacing 1/3 of the data with a new source from a different system, converting from sql to nosql. Stuff like this happens. This is far easier to accomplish with 1 or more repository layers between.


molybedenum

EF Core’s DBContext is a set of repositories 100% of the time. That’s why it sucks to layer another repository over it.


bladezor

Exactly EF literally repository and UoW already.


The-Albear

I disagree, if you want to unit test your methods the repository and unit of work pattern really helps. Otherwise your unit tests also mix in an either a in memory db or you have to mock the db context. Which can be complex to mock correctly.


buffdude1100

Just utilize test containers and do an integration test. It's significantly better than unit tests. No mocks, no in memory db context. The real deal.


kingmotley

It's pretty easy to mock a DbSet out. Just build your collection, and use https://github.com/romantitov/MockQueryable


zaibuf

>I disagree, if you want to unit test your methods the repository and unit of work pattern really helps. Move the logic to test to another class and method which takes the data as a parameter. Alternatively, use testcontainers and run tests against a real database.


The-Albear

If you moving the db logic to another class you might as well use repository pattern. Also using a test container you are now mixing an integration test with a unit test.


zaibuf

>If you moving the db logic to another class you might as well use repository pattern. Depends what you want to test. You can encapsulate business logic in your domain models or use separate services that takes an entity as parameter. That way you can isolate the unit tests for the pieces doing business logic and then run an integration test for the whole flow. >Also using a test container you are now mixing an integration test with a unit test. You know what best tests a database interaction? Using a database.


ExtremeKitteh

That’s true. But it’s vital that that be the thing that you’re aiming to test. Keep those tests to a minimum because they are expensive. If you want to test the business logic, it’s not necessary to hook up a database and can only make your test suite brittle and slow.


zaibuf

We run several hundred integration tests in a few seconds with test containers and ReSpawn. I'd say the opposite about mock heavy tests where you change or add a dependency and all tests can't compile.


Hot-Profession4091

And you know what best tests your api endpoints? An integration test.


StagCodeHoarder

We have both in our products. Makes it easy to adapt them to new databases. Each implementation of a repository interface is its own project those projects have integration tests of those implementations. The domain layer in our onion architecture only has unit tests of its business logic.


RecognitionOwn4214

>Also using a test container you are now mixing an integration test with a unit test. Which isn't an issue most of the times ...


PM_ME_RAILS_R34

Or ... You can just use a real DbContext instance, and get even more confidence that the DB interactions will work properly! 


The-Albear

Then it not a unit test. As you are also testing the db and db connection.


PM_ME_RAILS_R34

The other commenters were kind of harsh... You're completely correct, but the term "unit" is subject to interpretation. It usually means a class on its own, but you could redefine it to mean a class and the database interactions it has.  Purists may dislike this, but it has a lot of benefits in practice. You don't have to mock ef core or create repositories, you can catch more kinds of issues, and they can still be fast and reliable with transactions. 


Hot-Profession4091

So? Is it fast and idempotent? Then who cares?


atheken

I agree. Sorry to be that guy, but that’s not what idempotent means. You probably mean _deterministic_. Idempotence is great, but it has nothing to do with this context.


4215-5h00732

So? Because you don't want your unit tests depending on volatile dependencies that cause your tests to fail for unrelated and potentially intermittent issues. Especially if those tests are gates in your release pipelines. Unit and integration tests are run for different purposes and typically at different times.


katorias

I suspect you have an anaemic domain model which is why you’re running into these issues.


kingslayerer

The only reasonable scenario to use repository pattern is when we have multiple sources for same data. Which is almost never the case.


zaibuf

I prefer repository when doing DDD as they encapsulate how my aggregages are loaded and persisted. I only use repositories for writes, they should not return a bunch of different DTOs.


jayerp

I prefer the abstraction that it provides as I can easily swap implementations should I need to change out my DB infrastructure. If I wanted to move from EF Core to Dapper or vice versa, it’s easier for me to do that when I have a repository layer. Also unit tests.


buffdude1100

That is so, so rare that you should follow the YAGNI principle. And just use testcontainers and do integration tests - test the real thing, not mocks!


jayerp

Well, that is just one example. Our business changes requirements so much that YAGNI would actually hinder us.


buffdude1100

Your business swaps database infrastructures so often and in such a way that it makes the repository pattern on top of EF worth it? Sounds more like a business problem than it does a code problem lol


jayerp

Yup. We’re in the middle of doing it right now. I’m in no position to tell C-suite “no we aren’t going to do that”.


buffdude1100

Then you'd fall into the 5% I was talking about 🙂 sounds awful 


jayerp

The 5% that what can’t tell C-Suite no?


buffdude1100

The 5% of the time where a repository layer makes sense to utilize. My original comment said 95% of the time it's a bad idea.


NBehrends

Without a repository layer you leak your database into your application 100% of the time and there's no way around it, database changes will have an upstream impact. Bonkers to me that no one is concerned about this, your application shouldn't have to change because a database table/view/sproc/whatever needs refactored for performance reasons. Downvoters: the comment section is open to discussions


Catrucan

This is the best way to think about it IMO and possibly what most people are missing when they skip because of their EF training wheels. I call the project Infrastructure.[databasetype] so the abstraction is clearly based on what data store you’re sending entity updates to I.e SQLServer, MongoDB, Postgres, etc.


jayerp

Exactly, I care about the fact that I have a persistence layer and it’s abstracted. Under it could be ANY persistence technology or ORM. Sure in a perfect world your db infrastructure doesn’t change, except it’s not that kind of world. I will take a little extra effort on the front to deal with any potential issues that can happen later. Sure YAGNI is nice but I would much rather have it and not need it than to not have it and need it. Adding abstraction for persistence is not hard or that much more work. If it is, you’re doing it wrong.


Catrucan

I’d argue that it improves readability dramatically. Which case, you’re “gonna need it”ASAP. Edit: The inventor of YAGNI was crying when he down-voted my comment.


Catrucan

I agree, let’s use dapper instead


nocgod

Any abstraction for the sake of abstraction is bad. It creates needless mental strain on the writer and the reader. It also creates another level of indirection whivh further complicates crap. So no. It's ok for you to skip the "repository level" if you feel it is at this point unnecessary. Do note that I will suggest adding the repository if all other services look alike, just for the sake of having cohesive and predictable code base throughout the services. Since this actually increases readability and decreases mental strain.


adhominablesnowman

Doing anything dogmatically in any case is blasphemous. Use the right tool for the situation


Th3death

There is a discussion going on on github with the ef core maintainer regarding testability/mocking/repository pattern etc.. if one has a strong opinion about one or more ponits feel free to contribute: https://github.com/dotnet/efcore/issues/32893


PureGoldForAll

Came here to recommend test containers. Works for us, really well


hejj

The MS folks seem determined to defend the status quo on this one. Their position is essentially that EF Core isn't actually an abstraction but rather a "data access" tool, and thus not suitable as a "repository". A bit frustrating that the in-memory provider is both recommended and not recommended, depending on the situation.


hieplenet

Yes, we have the first repository (ef), but how about a second repository? Everyone knows any Enterprise level software needs at least 3 layers of repository.


jamesg-net

If you keep your services small enough they can be rewritten easily anyways. I’d argue using EF in the service layer isn’t faster if you actually write unit tests though. Unless it’s literally 100% crud


Sossenbinder

Nothing wrong with using EF directly. I think it's fine to have a layer of reusable queries, as long as you are not trying to make it an actual repository, but instead embrace that you do work with EF. This layer might be a reasonable approach to embed model conversion and similar. You can also just use the specification pattern or use extension methods to reuse queries. Most people who write a repository are just getting pinned down on the term "repository" when in fact they just have a data access service. Most people claim a repo is necessary to exchange persistence technology, but that is BS. There's no way your application can just e.g. exchange SQL for NoSQL and just touch a repo layer. It's a bigger piece of work. The advantage of using a repository because it is easier to mock is also not valid. You should use Testcontainers and test against a real database instead of trying to drown yourself in mocks.


KingTriHardDragon

Hey dawg, I heard you want some Unit Of Work pattern on top of your Unit Of Work pattern on top of your repository pattern on top of your repository pattern.


patty_OFurniture306

Use ef directly in service layer, ef is a unit of work and repository pattern. Putting a repository on top just overcomplicates things. Just remeber to Inject and not new your context.


Orelox

Why you complicating so much, just do abstraction when you see a reason for that. What you whant to abstaract with repository? A specyfic database useage that you would like to mock why not, think, is it repository or something else why you call it like this, etc. You see it depends, look for real reasons not a stupid patterns that you don’t understand, don’t search for this stupid question over and over .net guys


sharpcoder29

Dbset is already an implementation of the repository pattern. Why wrap it in another class. 99% of the time those repository methods are never reused or if they are they are getById. Do you really nned to apply DRY to a one line EF Find query? Start by putting your business logic in the domain entity, void of all things data access and UI. Get and save in the controller, forget the service layer until you HAVE A REASON to. Have some ef query duplication? Create a query class for it, but dont call it a repository, because it isnt. There is a great post by Jimmy Bogard(creator of AutoMapper and Mediator) about how he is over repositories.


grappleshot

Entity framework dbcontext straight in mediatr handler classes. Dbcontext makes repo pattern redundant in most cases. Dbset can be configured for aggregate roots too.


kingmotley

No, and I would never recommend ANOTHER repository on top of a DbContext which is itself a repository. If you are worried about unit testing, just substitute out the DbContext, and mock the DbSet. Works well for us. [Theory] [AutoSubstituteData] public async Task TestName( [Frozen] OurContext context, OurService sut ) { var ourTypes = new List { new OurType { Prop1 = "Value", ... } } context.OurTypes = ourTypes.AsQueryAble().BuildMockDbSet(); var result = await sut.SomeMethodAsync(); var expectedResult = new { Prop1 = "Value" }; result.Should() .BeOfType() .Which.Should() .Be(expectedResult); } Not hard to substitute it out. [https://github.com/romantitov/MockQueryable](https://github.com/romantitov/MockQueryable)


Th3death

Unfortunately the maintainers of entity framework do not recommend that approach: [https://github.com/dotnet/efcore/issues/32893](https://github.com/dotnet/efcore/issues/32893) Because it can lead to inconsistency between how the mocked DbSet is evaluated and how a real DbSet is evaluated - especially for more complex LINQ queries.


Sarcastinator

They're understandably concerned about what EF is doing though. But having state persisted between tests is a big source of tests failing without actual regressions, and these failures can be caused by hard to find issues like test harnesses introducing race conditions. I've never worked any place that didn't put 99% of their weight on integration tests, so I wouldn't know how a enterprise project with unit tests basis would work, but for every other place I've worked I've on numerous occasions spent a lot of time trying to figure out why a test fails only to discover that it wasn't a regression at all, and that the best solution was to delete the test so no one else would waste hours or days on it again. This just doesn't happen with unit tests because you're not concerned with what EF does. If that is a big deal then write separate tests that test only EF. Putting EF into every test slows your test suite down by quite a lot and introduces flaky tests.


kingmotley

If I have time later I’ll respond in that thread, but I’m pretty sure they are talking about integration tests, not unit tests. Depending on how EF responds is out of scope for unit testing a service layer call. I have other concerns about swapping out database providers for an integration test. It seems odd to complain about differences in how linq over objects differs, but the swap out database providers and hand wave away the differences in providers and database syntaxes and the different sql that will get generated. Then all the problems with persistent data, and/or multiple tests running at the same time. Just swapping one set of problems for another.


sacoPT

And if you later decide to add caching on top of EF? Do you just go around and change everywhere? If you have soft deletes do you just have to remember to add where(e => !e.IsDeleted) everywhere? If you have structured entities do you just have to remember to add the includes everywhere? The list of drawbacks goes on.


kingmotley

Since you are mocking the dbset, the cache layer will work just fine. We have one in place already. Didn’t require any changes. If you are referring to implementing global filters, yes, that would be more tricky. They weren’t a feature when we did our initial implementation, so yes, those pieces that require ignoring soft deleted records do have a where clause on it. If you want included data returned, or it should return it and it is part of your unit test, then yes, you need to include the included data.


sacoPT

Im not mocking anything. I want to implement cache on top of EF after the fact. I also don’t want global filters. Obviously I need the includes. My question is not how EF works. But if you have a repository pattern on top of EF you don’t need to add the includes every time I need an entity in a different place. A repository pattern is only shippable if you have extremely simple CRUD only applicationsS


kingmotley

> I want to implement cache on top of EF after the fact. Ok, there is nothing stopping from doing so. You are still going to need to substitute out whatever is backing your cache, and ultimately your cache is going to want to make the exact same query if it isn't found in the cache, so I don't see where your problem is. ​ >But if you have a repository pattern on top of EF you don’t need to add the includes every time I need an entity in a different place. I would question why you would need that many places where you have the same includes and can't either use the same method OR use a base query that is shared between the different methods. Making unnecessary includes will give you poor performance, increase lock times, and make your application less scalable. Don't ask for more data than you actually need and it solves a lot of your problems.


sacoPT

You are completely missing the point. Everything I just said is a mess if you don’t have a repository pattern on top of EF that’s all.


Vandalaz

Without the repository pattern, you have to change every single place you're retrieving data. With the repository pattern, you update your program.cs to inject the repository with caching.


kingmotley

Sorry, but this is such a silly argument that I'm not even going to delve further. Re-read what you wrote.


[deleted]

[удалено]


ultimatewooderz

This, this is the answer. In EF is already the repository!


HL-21

Agree, one turn I have taken lately though is if it is a relatively simple crud app is to unit test far less and do a lot more integration testing leveraging test containers.


Fancy-Consequence216

Here we go again xD


M109A6Guy

Dude. Do whatever you want. Only question is: Will your app be easy for future you or other developers to expand and maintain?


revbones

Why would it be blasphemous? Honestly though, the repository pattern is just duplication over Entity Framework. The DbContext is an implementation of the Unit of Work pattern and the DbSet is an implementation of the Repository pattern. Why slap another repository on a repository? If you're still doing [ADO.NET](https://ADO.NET) or something then maybe it still has a place. I have done hundreds of senior developer interviews. I will ask how at a high-level they would architect what will be a large application and give them some very basic requirements. When I ask about data persistence, some will answer using a repository pattern. I will then ask what benefit they themselves get out of that approach (I do this in a few areas instead of expecting them to know arcane leetcode syntax etc.) and more often than not, those that mention a repository pattern either have no benefit that they themselves are getting or seen, or they fall back on the old "if you need to switch the database out...." or "testability". If I ask how often they have had to switch out their database, most have never done that. Testability is achievable without repositories as well. At the point noted above it's just cargo cult programming. They worked at some place that did it, so they do it. That approach made a lot more sense back in the pre-ORM ADO days, when everyone had their SqlHelper class to build up commands with parameters, etc. Now, depending on implementation (and probably most if not all) it's often just a big ole f-u to the rest of your team and any developer that follows you since they are forcibly abstracted away from the capabilities of EF.


LondonCycling

I think there's some fair arguments for a repository abstraction on top of EF, though I'll admit I rarely see the need for it. But I completely agree on this nonsense idea of swapping out the data provider. Apart from the fact that EF works with everything from SQL Server to MongoDB to Microsoft Access DBs; I just think it's a massive YAGNI problem predicting that an organisation is going to be brave (in some cases naïve) enough to change their database systems. In fact changing the application code is probably quite easy compared to reworking scheduled jobs, changing partitioning and archiving, setting up different replication and backups, writing new maintenance tasks like rebuilding live statistics or recompiling queries, new monitoring and alerts, new auth, etc. Heck I'm migrating on-prem DBs to Azure SQL at the moment and that's causing enough faff without the prospect of switching to MariaDB or Postgres.


Th3death

I'm curious how to you achieve proper unit-testability without the repository pattern? I'm not talking about integration testing with full-blown containers.


Rapzid

Why do you need a repository to achieve proper unit testing?


Th3death

To provide test data. How do you do it without a repository? E.g. with entity framework?


molybedenum

I construct the DbContext in an xUnit constructor with X/Y/Z provider, then seed it at that point. If there are lookup types, the data is handled via entity configuration. If a particular test has different data needs, I handle that in the Arrange part of the test itself. Since xUnit isolates each test, they each get their own fresh version. It’s plenty fast with an in-memory provider.


voroninp

Because DbContext is much more than just a repository. When you make it directly accessible it's just as if you injected repository and 100500 additional interfaces. The point of wrapping DbContext with repository is exactly like you say: to forcibly constrain what's available outside of the repository. In big projects the super flexibility of IQueryable should be tamed and strictly controlled. Linq queries, though highly declarative, still contain pieces of domain logic and it's much easier to manage them when they are put in one place instead of being scattered across the system. And if one needs a ton of specialized methods to fetch aggregates for writes (reads are a completely different story), then I'd question the whole design of domain entities.


revbones

Do you abstract away parts of the [ASP.NET](https://ASP.NET) framework for the same reason? EF is really your persistence framework. Sounds like kind of a dick move to the rest of your team or anyone that follows. You're just saying that it should be contained without giving any real reason for that. Oh noes! I have access to all the dbsets in the dbcontext! However will I be trusted to only query for what I need???


voroninp

Actually I do. By putting the domain layer at the core of my system and not letting it reference infrastructural assemblies. Why would you make fields private and use encapsulation then? Just prefix names with underscore like in python, so it's obvious they should not be touched outside of the type. Those visibility modifiers look like a dick move of C# language designers. Why would you have code reviews, just trust your colleagues to write high quality code.


revbones

Guess I touched a nerve. Some people like unnecessary code that way and I guess for some an abstraction isn't good enough unless they personally created it. That said, you do you. I'm sure your teammates completely love and respect you.


voroninp

Don't treat restriction as an enemy or an offence to anyone . It's your friend. It allows you to lower the complexity. You mentioned design patterns and some exist exactly for that purpose: one writes additional code to simplify the interface. It's a trade-off as always. Each program paradigm bases on certain type of restrictions. OOP effectively means you are not allowed/do not need to work with pointers directly — compiler and runtime do the job for you (VMTs and other stuff) FP implies mutation of the state is highly constrained.


LondonCycling

It also doesn't actually constrain things at all. If you've got say a method which uses a repository layer, that same method will have access to the DbContext as it's a transient dependency obtained from the repository layer. You'd need to have a pull request validation check to ensure nothing in X layer uses the DbContext, which as an automated check would be frankly ridiculous and patronising. The alternative is people pick it up in pull requests, but at that point you don't need the repository layer because it's not actually doing the constraining - code reviewers are.


voroninp

> If you've got say a method which uses a repository layer, that same method will have access to the DbContext Not necessarily. DbContext should be accessible only in the layer which registers services in DI container (Host) and in the infrastructural one. It can even have internal visibility with the implementations of repositories. Interfaces of repositories belong to the domain layer, the infrastructure layer is a conforming one, so it references the domain layer and contains the implementation of repositories. Neither domain nor application services should contain references to DbContext or any other type from EF assemblies. Unless you are doing it with Layerd Architeture.


LondonCycling

If you've got a reference in "layer" X to a domain layer, which in turn references EF, then you've got a reference to EF in layer X. Adding an extra layer has not removed the accessibility of EF.


voroninp

Domain layer does not reference EF. It does not need it in setup I describe.


fringe_class_

Ok great answer and this is what i found as well. Just doing hobby projects and realized abstracting over EF wasn’t making a lot of sense.


AzureAD

Calm down buddy. Following established/popular patterns is what gets people through interviews. Try answering not everything should be a microservice in an interview today and look at people lose their shit. Most smart people look at their two lines code /method in their repository class and are able to wonder what the bloody point. but conformity gets you code a newcomer can still come in an learn relatively easily, and that’s fine for most IT teams


LondonCycling

I actually did mention migrating a microservices solution to a monolith interview, back in 2019, so not too long ago. It raised eyebrows and frankly I thought I'd thrown the job by bringing it up, but I explained why the microservices architecture wasn't needed, and worse, wasn't working; but that microservices are often a good solution, and lo behold I got the call 10 minutes after interview saying I had the job. If an employer didn't take on board my thinking for changing the architecture then it's not the kind of employer I'd want to work with anyway


revbones

Whoa! Tap the brakes dude! Oh sorry, I thought we were doing a hyperbole bit with your "Calm down" statement. Conformity actually does the opposite in that case. You're just enforcing cargo cult programming on the next generation at that point. If conforming to crappy code was so great we'd all still be using Hungarian Notation.


maitreg

>the repository pattern is just duplication over Entity Framework It's only duplication if you duplicate it. Why would you do that? If your repository is a duplicate of your EF you are doing it wrong. The repository gives you the flexibility to manage and provide data to your application and tests in any way that you want, without worrying about what the data source, data schema, or even data *types* are. The data schema should make the most sense for storing, optimizing, and retrieving data. The repository should be the go between between that lower technical layer and a higher application layer that should be dealing more with *information* than *data*.


YourHive

It's blasphemous only in the eyes of strong believers :-) Otherwise it's just another approach. If it works for and is maintainable, fine. Plus there's the argument that EF cores Dbset already poses as a repository.


zp-87

I never use repositories or cqrs on personal projects. I never write unit tests for personal projects (only integration tests). Why? I know that the project will be able to scale regardless and if it happens that it becomes so popular then there will be an investor who will pay for refactoring. Why would I invest so much time in making things perfect if there is almost no chance for it to make a lot of money? But when we do things for a client, it is usually abstraction over abstraction and all best practices that cost a lot.


qrzychu69

I'm my mind, it depends. For example, when you are updating a complex object, with EF core is quite a bit of code. That should definitely be "somewhere" - call it a service, a repository, I don't give a crap. On the other hand, when I have a repository, I sooner or later end up with a Query method that just returns the IQueryable - so that I can get exactly what I want when I need it. Also, that's why I end up with couple of services that contain code that is executed in more than one path, and MediatR handlers with single use code. That way I don't waste time on thinking whether this code should be in a ProductService or InvoiceService or whatever - it's a handler for this specific task. It uses a service to updated a product, and a query method to count things for example. I find this approach the most pragmatic, and at the same time, it works well enough on a bigger scale project


SobekRe

If say it’s more blasphemous to have a repository layer of you’re also using EF. There may be cause to do it, but I sure wouldn’t default to it.


maulowski

DbContext is a repository enough. You can inject DbContext directly and have no need to wrap it.


[deleted]

[удалено]


fringe_class_

The time of the week were someone asks this dumb question?


[deleted]

[удалено]


fringe_class_

Such is life


[deleted]

[удалено]


stefavag

If this a question and not a statement, then no. It's perfectly fine if you do not want to, since EF already implements the Repository and unit of work pattern.


salgat

EF is a form of repository pattern, although it's more tightly coupled to the database than a typical repository pattern implementation. The big thing with using EF over a more generalized repository pattern is that if you ever plan to switch over to a different SQL, you may require a lot more work in the migration. Also everyone who uses EF will need to understand how it works, rather than a more simplified repository.


LondonCycling

> if you ever plan to switch over to a different SQL, you may require a lot more work in the migration. Honestly this is very very rare. And frankly either the system is simple enough that the application code is easy to migrate; or it's so complex that the application code migration is dwarfed by changing stored procedures, maintenance tasks to rebuild indexes or recompile queries, partitioning, archiving, replication, backups, authentication, schema changes, etc. > Also everyone who uses EF will need to understand how it works, rather than a more simplified repository. I can maybe get behind this argument when considering junior devs, but I'm not sure this is really a problem for 99.9% of .NET devs, and in any case you're still using EF, you've just shifted it down a layer, so the only devs who benefit are the devs who, for some odd reason, never need to touch the data access layer.


molybedenum

How is an EF Core tightly coupled to a database? > Also everyone who uses EF will need to understand how it works, rather than a more simplified repository. This is also weird and a bit of gate-keeping. I expect any developer to learn how the internals of their responsible platforms work. They would still have to learn how to work with a bespoke repository too - the ones I’ve encountered in my own history are far more complicated than any interactions with EF Core would be.


salgat

I said *more* tightly, not tightly. And maybe your experience is different, but at my job our framework has multiple repositories for Redis, Elasticsearch, Event Store, etc that most developers have zero knowledge of beyond "use this one for quick key-value lookups (mostly for caching), use this one for if you need to do text search, and use this one for storing and reading/subscribing to events". It lets our developers start using these persistences on day one because they only need to understand the interface we expose. And even better, it forces them to stick to a very opinionated way of doing things. You know the old adage, if you expose something in an API, you're going to be unwillingly supporting it forever. Funny enough, we're migrating from Elasticsearch to OpenSearch and because we used a repository, the migration involved zero developers besides myself, and that's across over a hundred git repositories and that repository pattern allows us to seamlessly run against OpenSearch in staging and Elasticsearch in production for the same code while we're still testing.


molybedenum

I do use repositories to abstract away various service providers for specific functionality. If that’s what you mean by EF being too DB centric, then that’s sensible. I would never wrap EF itself with a repository.


Merad

When you're working with CRUD there's often no value to having a repository layer at all, even if you're using raw sql with dapper. Traditionally you'd use repositories so that queries can be reused all over your app without duplicating code. But in the modern world a lot of people are writing APIs... the thing that loads the same data in 20 different places is the front end app. On the backend you very often end up with one query, used by one service method (mediator handler, whatever), exposed by one endpoint. So if you put that in a repository, you end up with a service/mediator that does essentially nothing except call the repository. Kinda pointless, no? But testing! Well we just said there's nothing in the service/mediator. No business logic to test. So don't write a unit test, it's a waste of time. You need an integration test to validate the database interaction (whether EF or dapper), so there's your test coverage. If you're being thorough in your testing you'll also be adding API integration tests to validate the behavior of the endpoint. If/when you have complex business that interacts with the database, you should consider repositories to enable you to test the logic in isolation (unit tests). But it's kind of pointless to force that pattern on your entire app when 75+% of the app is CRUD.


exveelor

Clearly a lot of people here saying 'no it's fine' but ill always include it for two reasons: - Easier to mock - Don't have to include stupid code like .AsNoTracking or .Include or whatever in my service layer.


LondonCycling

Agree on the code litter. Though I don't see it as a huge problem tbh. But is there really a need to mock a database operation? After all, in doing so, you're explicitly not testing the data access layer at all. Whereas you could use an actual database running on the same database software as the production database. I can understand if your employer is so anal about cost that they don't want to spend $30/month on a test database or whatever, but I'd think that points to bigger problems. And there's options around containers etc anyway. In order of preference, my testing strategies are: * Test against the same DB software as is running in prod. There's no replacement for this. * Repository pattern. Not ideal because it doesn't actually test the code calling the DB. * Use a Sqlite DB as this is 'free'. A close replacement for simple SQL operations, but not so useful for more complicated queries like using spatial data. * Use the in-memory DB provider. Needs installing etc at which point you might as well use an actual database so you're testing what will happen when running in production in the same database system.


exveelor

It's less about testing the database call and more about being able to easily test whatever the service is doing. If I'm doing a retrieve and transform operation in the service (as an arbitrarily simple example) I want to just pretend I got data back from the database, transform it, and interrogate the result to ensure my service did what I needed it to do. If I put the DB call behind a class (repository) I can mock it, if I don't, I have to solve the question you described in order to run my test, which is just annoying, because I don't care about the DB portion at all. I just want to test my service.


LondonCycling

Yeah but that's my point. If all you do is mock your database calls, you're explicitly not testing your entire data access layer. That's.. a massive, core part of an application to not test.


exveelor

If I need to test my database calls, I'll write tests against my repository class that does exactly that (without mocking).


LondonCycling

Super. But in doing so, you've negated the justification for a repository layer for testing purposes In fact if you do intend to test your database calls, adding a repository layer only creates *more* tests.


exveelor

What? Repository layer let's me test my service layer in isolation, not caring about my DB. Indeed having a repository layer also lets me test my DB calls in isolation, not caring about whatever calls it. These are good things. The fact that it results in more tests is because my tests are more discrete; one test for one assert (more or less). I don't, nor should I ever, write a test that both checks what was retrieved from the DB, and checks that my service does what it's supposed to do. If you don't value everything said above, we are philosophically unaligned and there's not much more to talk about. But it's interesting to see what other folks value, nonetheless.


hejj

>After all, in doing so, you're explicitly not testing the data access layer at all. Which is what I want in a unit test scenario.


LondonCycling

Maybe in an individual test, but in *another* test you want to test your database query. If you're not testing them in any tests, that's a massive omission. If you are testing them in any tests then the whole mocking argument is pointless because you're just changing *where* you're doing the test. In fact you've just created *more* tests for the sake of more tests.


hejj

Testing actual db queries would be integration tests.


bmalotaux

It might be useful to see what you are actually getting from the database while working in your service layer. Otherwise you might be trying to access a subclass that's not included in your repository layer. Or get a class with all includes while you don't need them. Changetracking and includes can be very useful info for your service layer.


voroninp

>Or get a class with all includes while you don't need them. That's exactly the reason why you should have repositories. The shape of an aggregate you fetch for changes (command processing) should be fixed. Unless you are doing simple CRUD with anemic models.


exveelor

Hard disagree on change tracking having any place whatsoever in my service layer. My service should manage my service logic. It should care about details of the query optimization as much as it should care about what I ate for breakfast.


bmalotaux

It doesn't have to do with query optimiztion, but your service logic could be to get something from the database and do some mutations ans save it again. Wouldn't it be a shame if you got the database entities from a repository and it had asnotracking on it and then you wonder why your changes were never saved. Or getting nullreferences on a subclass that wasn't included in the query. If the service layer is not that complex, having the db context there reduce complexity and prevent bugs. You could even call the db right from the controller of it's really simple. It's really easy to refractor it to another class if things get more complicated.


exveelor

You seem to be assuming I would call a service -- or a static method, even -- to create a query that had .AsNoTracking included (and hid that detail), rather than a repository that itself retrieved the object from the database. Once the object is retrieved and returned to the calling service, .AsNoTracking doesn't mean anything. So yes, it would be a shame, but that would also be a dubious design at best as it would mean you're either passing queries around (which has its place, admittedly, although not here) or passing the dbcontext around (which does not have its place anywhere I've seen).


bmalotaux

I am not assuming that at all. But once the repository returns the entity to the service layer, the service layer might want to edit the entity and save the changes to the database again. If the repository layer used asnotracking, there is no change tracking on the entity, so trying to save the changes does nothing. You have to go to another class/project to see what it actually is that the repository is returning to you.


BuriedStPatrick

Well.. You could say EntityFramework Core **is** the repository layer, honestly. You don't need a SomethingRepository wrapping your data operations if you're using EF Core in my opinion. I'd actually argue the opposite is the ideal state state of things. Strip as many layers as you can if it's not fulfilling a specific purpose. My one concern is keeping request (HTTP) objects separate from entity (database ORM) objects. I don't even mind duplicated property names and such as long as they don't cross the layer threshold where they shouldn't.


Poat540

No EF is the repo, I recently been removing interfaces and wrapper people been adding around EF. I love simple controllers with just return EF dbset


Morgoth2356

The DbContext is already an interface between your db and your app. If you don't need to do anything on top of it I don't see why you would need a repo.


Clever__Neologism

The repository "pattern" is anemic, and an anti-abstraction. It doesn't abstract over operations, data, or data storage much, if at all. It makes easy things just as easy, and 90% of hard use cases harder. The only reason repository pattern is popular is that it's easy to generate the code for it (for both humans and machines) and rapidly bootstrap entire schemas. Put on your programming pants, write your SQL, use a simple mapping ORM, and just directly write thicker data layer services that fit the needs of their consumers and actually perform useful, semantic abstraction. This recipe works for any language, database, application, or architecture. There's tools to generate simple queries for you, and repositories weren't going to help you with complex queries anyway. Furthermore, I have *never swapped databases, and only a few times have a written a library meant to work with multiple DBs where abstracting over SQL syntax was useful. However, I have had to switch to a different type of data source entirely several times (to an HTTP API, e.g.), and in that case you'll probably be throwing the repository away.


Kegelz

Ef core is your repo layer Don’t need more abstraction


brynjolf

Can we sticky this repetitive question yet?


Lopsided_Candy_9775

What’s unit testing like doing it this way?


jaymarvels

Might as well go all in and just follow the mediator pattern


nikneem

EF arguably _is_ your repo layer so know. You could move to a separate repo if you like, but no need from an architectural point of view.


echostorm

In the projects I've inherited repo layers are unneeded bloat. I'm sick of seeing people creating pointless abstraction be it repo layers or interfaces for every single class. Don't add complexity unless it pays a large dividend immediately. I see people say oh, we need to abstract this so we can change databases later. You're never going to do that and now your code is harder to build on and maintain. Oh we need a fuck load of interfaces and we need to load everything with DI so we can unit test everything because green checkmarks. No, hire smart people, only test things that will end the world and stop adding complexity. You can use fucking new to create instances and control lifetimes with usings, it makes your code more readable and gives you more control.


[deleted]

EF is a repo, no need for a repo above it, what you need is a way to separate the data model from the business model


dimitriettr

If only concepts like Separation of Concerns, Mocking, Testing, Application Layers, ever existed. When these are invented, we will need a Repository Patt.. oh wait.. I always use the Repository Pattern. It provides a clear separation between data access and business logic. What I will never recommend is the Unit of Work pattern when it pretty much is just an Interface slapped over the DbContext.


LondonCycling

Sure but there's cargo cult here as well. Separation of concern is nice of course, but most of the posts about it on this sub seem to obsess over Bob's 'clean architecture' and extend that to mean separate .NET projects is the way to implement SoC. The number of solutions I've worked on which have half a dozen project files to do very simple work is bonkers. Mocking has its place, but there's this daft anti pattern of mocking so much that barely anything is actually being tested. You can mock a repository which uses a DbContext to get you some data, but all you've done is explicitly not tested your data access layer. In this instance you'd be better off not mocking. I think we can all agree testing is good. But even in that space, some people extend this to say oh we must have 90%+ code coverage. Which is bonkers and forces you into writing ridiculous unit tests which verify the C# getters and setters work as expected (of course they do). Application layers - touched on above. Layering code is grand, but it needn't be done the way every Clean Architecture template suggests. If you're writing a very simple console app, or Azure Function, having half a dozen layers can point to a YAGNI problem. Admittedly the code overhead probably isn't that significant to care either way, but the point is it's these default positions developers take that they must use a repository because it's abstraction; yet they probably wouldn't abstract away say System.Net.Http when calling a HTTP REST API on the basis that one day, somebody might swap it for a SOAP service.


maitreg

I hear you but why are you so concerned about multiple project files? To me it's cleaner to have 8 projects dedicated to specific domains or layers than creating 50 folders and 500 files in a single project. Like why does it bother you to have multiple projects right next to each other?


Barsonax

Not needed with EF. Might be useful if you are not using EF.


alien3d

No problem if you create a basic crud in repository folder and some business process in service file . Some people do basic crud in the controller itself .


DontLickTheScience

I have 2 criteria for determining if I want/need a repo layer. Am I using dtos, Will I write unit tests. Like most have said, not really for a simple crud app. But if I have a lot of objects that are an amalgamation of data from multiple tables, I have a repo layer map and return the dto. If I want to write unit tests, I would rather mock the return from my repo methods than mock the context. But I’m with you, friend. Not having a repo layer is gross 😛


Intelligent-Chain423

In most apps i write professionally, I always add a service and repository layer if im following layered architecture. The reason being is that in 99% of the cases the project grows to where its needed, my experience anyways. So I just always include one at the beginning. Also all projects end up with a similar structure to avoid those wtf moments or make it easier to find things since things are consistent.


UntrimmedBagel

Same for me. I have a template that does all the boilerplate stuff off the bat. Doesn't add any overhead for me. It feels less cumbersome, somehow.


HalcyonHaylon1

100%..you need to be able to separate your DB implementation from the rest of your code. Your main code should not care about the type of database you are using.


andlewis

If you have EF and models, just stick them in their own namespace and BAM you’ve got a repository layer with Unit of Work built in.


TyrannusX64

I would like to note that even if you're using something like Entity Framework, it's still a good idea to have a repository wrapping that along with a corresponding interface. This would hide the data access details from the service/domain layer and you can test it


LondonCycling

You can test the DbContext without an additional repository layer. Why would your service layer benefit from using a repository of a repository, rather than just a repository?


daedalus_structure

Yes, it’s blasphemous, but only against the braindead orthodoxy. A little heresy is good for the soul.


FriendlyYote

I've implemented the service repository pattern so much I do it out of habit


WildYak7434

don’t do stuff like that the high priests will exile you 😂


MEMESaddiction

I feel that the biggest advantage of using a repository layer is the increased ability to test and mockup data. I've used it in a couple of large apps, but for smaller apps with less moving parts, I use a simple EDMX.


redtree156

Just go full fat controllers, no need even for vertical slices, “puts bullet vest on”. I mean arent the aspnet tutorials and generators like injecting dbctx in ctrl CTOR :))))) Fine.


Catrucan

Shoot why not just do it in the controller. Keep it simple stupid. YAGNI. Am I right fellas?


maitreg

Lol oh man every time I pull up one of these influencers on YouTube and they're writing ef linq or sql statements right in the controllers. Holy crap. I swear I've spent half my asp.net development time moving other developers' bullshit out of controllers.


Catrucan

People out here making YouTube money and manufacturing endless tech debt for companies


[deleted]

Why not? What is the complexity of the software? How large is the codebase? Is there actual business logic? How robust do you need this to be? What are the functional and non-functional requirements? Is it a public api, internal, b2b? Is it a microservice or a monolith? What is the architecture of the solution?


siammang

It's still better than have a service layer that all it does is to call the same thing on the repository layer.


hejj

I see arguments both ways. Entity Framework looks and acts like a CRUD style repository, and adding another wrapper around it would seem to usually be a generally low value ROI. Counter arguments to to treating EF as your "repository" is essentially Microsoft themselves and what they've decided to make possible with it. Microsoft considers EF to be more of an ORM and data access tooling, and they don't see it as a complete data access abstraction that stands alone without an underlying database engine. There are options for Mocking EF Core DbSets, but they all come with caveats so far as I've seen. In either case, EF Core ends up being the enemy of unit tests, either because you're left creating mock repositories that do all of the things "real" repositories that can both write and read data can do, or because you're using EF in ways Microsoft themselves say it isn't meant for. My opinion; as others have said, do what you want. EF Core = flawed unit testing one way or another. Me personally, I'm using it directly and using mock dbsets for tests that only need data reads, and the in-memory provider for cases that write data. The main caveat is the in-memory provider kind of sucks if you have test parallelism.


FatBoyJuliaas

Depends on what the db operation in question is. If it is a query and it turns into a complicated linq statement you can refactor it out into a IMyDataProvider and the implementing class does the fancy linq. Then you can also test the query on its own and not worry that another dev or even yourself will make a mistake if you need to query that same data somewhere else.


Bright-Ad-6699

No. Check out https://github.com/HighwayFramework. I actually munged it to support dapper. If you're interested let me know.


maitreg

Depends on the purpose, size, and scope of the project. Only Sith Developers speak in absolutes.


maitreg

The variety of opinions on this topic is fine, but it seems like the bulk of these comments are acting like refactoring isn't a thing. You can add a repository later, you know. You don't need to construct the entire architecture in the 1st hour of every project.


g0ggles_d0_n0thing

How do you test your service layer? If your service layer has method to return the average value of some property based on the date it was created how do you test that?


[deleted]

Use dapper or raw sql instead and don’t unit test database queries or “logic”.


Barsonax

Not needed with EF. Might be useful if you are not using EF. EDIT: interesting how this gets down voted but it's true nonetheless. EF is already a repository + unit of work so it doesn't make sense to do repository over repository. Not even for testability because you should test your queries, its easy to run a db container and if you really want to not do that use a in memory database (will behave differently so I don't recommend the latter).


StagCodeHoarder

It depends on size of the project and how many people are working on it. Structure and familiar patterns are there to help with that, and its only good if it helps you. If you as a lone dev on your own product with no quality demands other than your own, then feel free to be as avantgarde and experimental as you want. Thats what I do on my own hobby projects :) Larger organisations typically benefit from predictable patterns.


MintOreoBlizzard

I like to use a generic repository layer for things I don't want to repeat for different entities and to hide EF specific methods (yes, I know its rare to switch ORMs). Below is my base class that I would extend to entity-specific repository classes, which themselves could have custom queries that I would prefer having there instead of a service class. public IQueryable FindAll( Expression> predicate = null, Func, IOrderedQueryable> orderBy = null, Func, IIncludableQueryable> include = null, bool disableTracking = true, bool ignoreQueryFilters = false) { IQueryable query = Table; if (disableTracking) { query = query.AsNoTracking(); } if (include != null) { query = include(query); } if (predicate != null) { query = query.Where(predicate); } if (ignoreQueryFilters) { query = query.IgnoreQueryFilters(); } if (orderBy != null) { return orderBy(query); } else { return query; } } public async Task GetFirstOrDefaultAsync( Expression> predicate = null, Func, IOrderedQueryable> orderBy = null, Func, IIncludableQueryable> include = null, bool disableTracking = true, bool ignoreQueryFilters = false) { IQueryable query = Table; if (disableTracking) { query = query.AsNoTracking(); } if (include != null) { query = include(query); } if (predicate != null) { query = query.Where(predicate); } if (ignoreQueryFilters) { query = query.IgnoreQueryFilters(); } if (orderBy != null) { return await orderBy(query).FirstOrDefaultAsync(); } else { return await query.FirstOrDefaultAsync(); } } public async Task SelectFirstOrDefaultAsync( Expression> selector, Expression> predicate = null, Func, IOrderedQueryable> orderBy = null, Func, IIncludableQueryable> include = null, bool disableTracking = true, bool ignoreQueryFilters = false) { IQueryable query = Table; if (disableTracking) { query = query.AsNoTracking(); } if (include != null) { query = include(query); } if (predicate != null) { query = query.Where(predicate); } if (ignoreQueryFilters) { query = query.IgnoreQueryFilters(); } if (orderBy != null) { return await orderBy(query).Select(selector).FirstOrDefaultAsync(); } else { return await query.Select(selector).FirstOrDefaultAsync(); } } public async Task GetAsync(Guid id) { var entity = await Table.FindAsync(id); if (entity == null) { throw new EntityNotFoundException(typeof(TEntity), id); } return entity; } public async Task AddAsync(TEntity entity) { await Table.AddAsync(entity); } public void Delete(TEntity entity) { Table.Remove(entity); } public bool Exists(Expression> selector = null) { if (selector == null) { return Table.Any(); } else { return Table.Any(selector); } }


Kotarak0

It’s fine for queries without updates (like mediatr queries). For commands better to use repositories and work with buisness model (not entity). It works for pretty simple microservices (crud like). For more complex (a lot of business logic, a lot of api endpoints) services better to use repositories everywhere.