Awkward Generic Repository Call - c#

I am implementing a generic repository pattern, I have done this quite a few times now but every time I do it there is something bugging me.
If I have a database design like below. (All the tables relate to one another.) And I make a call like the following
public IEnumerable<Domain> GetRealEstate()
{
return _repository.GetAll();
}
I can get all the models from just that one call (The wonders of EF). The thing that bugs me is the fact that I have to say Domain in the method call, from the domain entity I will get all the relevant entity (Lazy loading) Companies etc. etc. It just feels wrong to use domain entity to get all the companies etc. etc. The repo pattern that I am using is a straight forward one.
Is there a better way of writing the methods so that it does not look so weird?
Below is sample code that i have
Controller
[RoutePrefix("api/realestate")]
public class RealEstateController : ApiController
{
private readonly IRealEstateService _service;
public RealEstateController(IRealEstateService service)
{
_service = service;
}
[Route("")]
public Task<Domain> GetRealEstates()
{
var collection = _service.GetRealEstate();
return null;
}
[Route("{domainName}")]
public Task<Domain> GetRealEstate(string domainName)
{
}
}
Service
public class RealEstateService : IRealEstateService
{
private readonly IRealEstateRepository _repository;
public RealEstateService(IRealEstateRepository repository)
{
_repository = repository;
}
public IEnumerable<Domain> GetRealEstate()
{
return _repository.GetAll();
}
}

Sense & Responsibility.... This is a dilemma I see more people struggle with. I think the key to feeling easier about it is that Domain can be considered an aggregate root that encapsulates the whole object graph it's the owner of.
Let's look at a very common example that's closer than you might think, DbSet. DbSet is a repository. But I think most of us think it's totally acceptable, even good practice, to write a query like
context.Domain.Include(d => d.Companies)....
Nobody will say, what has a DbSet<Domain> to do with Company? Even when we add a Domain to the DbSet, and by doing that we add an entire object graph, nobody will feel any inclination to add each object through its "proper" DbSet. That would a totally useless hell of a job.
If this wasn't good practice, EF (or any ORM) wouldn't have navigation properties. Think of that... nightmare.

Related

Mapping and querying the web api in service layer

I am making a web api and have created several classes, the class controller and the service as well as the dto and the model.
In the controller I have the methods for post and get and the business logic is in the service
My question is how can I make the queries from the model class and map the queries to the dto
Service Layer:
public class GermanyService : IGermanyService
{
public Task<IEnumerable<GermanyDto>> All()
{
throw new NotImplementedException();
}
public Task Create(GermanyDto germany)
{
throw new NotImplementedException();
}
}
Controller:
public class GermanyController
{
private readonly IGermanyService _germanyService;
public GermanyController(IGermanyService service)
{
_germanyService = service;
}
[HttpGet]
public async Task<IEnumerable<GermanyDto>> Get(int id)
{
return await _germanyService.All();
}
[HttpPost]
public async Task Post([FromBody]GermanyDto dto)
{
await _germanyService.Create(dto);
}
Okay :)
Use an interface implementation ->
seggregate your business logic's interfaces, so you have many of them, split into their single responsibilities and then join them in one:
Example
public interface IStreetName {
string StreetName{get;set;}
}
public interface IPostCode {
string PostCode {get;set;}
}
... other implementations for an Address DTO f.x.
then
public interface IAddress : IPostCode, IStreetName, ...
{
//should be empty
}
now you can Implement Iaddress on your DAL object, and not need an actual DTO -> because you ONLY reference the interface in your business logic.
etc.
Obviously, you would have to rename the intefaces for the properties on your "GermanyDTO", which I don't know what looks like.
EDIT:
Using mappers like "auto-mappers" or the like is usually a sign of 2 things.
1: You don't understand how to write effective mapping yourself.
2: Using a framework to accomplish something, doesn't absolve you from testing. And frameworks are notoriously difficult to test.
(Because, following proper procedure, you would have to test the interface between your code and the framework, and by extension the code between framework and 3rd part component, failing to do so, will setup you up for risks, between what you THINK the framwork does, and what it ACTUALLY does)
So Yes, using something like "Automapper" is at best a supression of a symptom rather than a cure.
Because the root cause is failing to understand how interfaces solve mappings.
And using a tool, to do something you can do cleaner yourself, and improve the structure of your entire system as a result? Is a no-brainer.
Just notice your own statement:
"Do you think it is effective? Automapper solves some of my issues"
You are seriously going to implement a direct dependency in your system, because of a framework?
You are admitting to writing bad code, because a framework can take away ... what? A little bit of boiler plate?

Where should I put the complex queries using the Repository Pattern?

I have an application in which I use Entity Framework, and I have a class called BaseRepository<T> with a few basic CRUD methods, such as (Get, GetAll, Update, Delete, Insert), and from this class I generate my specific repositories, such like BaseRepository <Products>, BaseRepository<People>, BaseRepository<Countries> and many more.
The problem is that, when I have a complex logic in the service, that involves making joins of several tables and that does not return an entity, but an object that is handled in the service (it is neither a DB entity nor a DTO), I find that repositories don't help me much with just basic CRUD operations.
Where should I put this query complex? in which of the repositories should it be? How do I join these repositories? The problem is that I see that the repositories handle a single entity, what should I do in this case? I've been doing some research and read that returning IQueryable<T> is bad practice, so I rule out that possibility of sending IQueryable<T> of the tables I'm going to join the service and do it there.
I've researched and found no clear answer. I would like to know how and where these complex queries are organized, since I also want to respect the responsibility of each repository with its respective entity.
I would like to know how and where these complex queries are organized, since I also want to respect the responsibility of each repository with its respective entity.
The complex queries are the responsibility of the code that is requesting the data, not the responsibility of the repository. The single responsibility of the repository is to provide access to the data, not to provide every possible request shape that may be needed in any use case. You really want to write methods in your repositories like:
customerRepo.GetCustomerWithLastTenOrdersAndSupportCasesAsDTO()
or
customerRepo.GetCustomerForCustomerSupportHomePage()
Of course not. So your repository provides a property of type IQueryable<T> or DbSet<T> which can be used as a starting point for consumers to add whatever queries they need.
I've been doing some research and read that returning IQueryable is bad practice
Don't beleive everything you read. There's really not a good alternative to exposing IQueryable<T> from your repository. And once you digest that, there's not much of a reason to have any repository type other than your DbContext subtype.
Its hard to answer without having a code to understand what you want to achieve, hopefully my answer gives you an idea on how you can use abstract classes to override your Queryable Collection. If your requirement is more complex, can you provide more information with example code.
Create your BaseRepository like this -
public abstract class BaseRepository<T>
{
public IQueryable<T> Collection { get; set; }
public readonly DbContext _context;
public BaseRepository(DbContext context)
{
_context = context;
Collection = SetQueryableCollection();
}
public virtual IQueryable<T> SetQueryableCollection() => _context.Set<T>();
// CRUD Operations here for e.g. -
public virtual async Task<List<T>> Get()
{
return await Collection.ToListAsync();
}
}
Now, the class that inherits this -
public class ProductRepository : BaseRepository<Product>
{
public ProductRepository(MyContext context) : base(context)
{
}
//now override the method that sets the collection
public override IQueryable<Product> SetQueryableCollection() =>
_context.Set<Product>().Include(p => p.Brand).ThenInclude(...);
// things to keep in mind, the _context is public in the way I've done it. You can change that and directly expose the Collection and set it to your need per entity type.
}
So now your GET method uses the overriden method to set the Collection.

Should repositories be properties on the unit of work when using Entity Framework?

I have scoured the web looking for a good implementation of the Repository/Unit of Work pattern using Entity Framework. Everything I've come across is either tightly coupled at some point in the abstraction or assumes that the DbContext used by the Unit of Work and Repositories is shared and should live for the entire HTTP request (instance per request via dependency injection).
For example, assuming you are consuming repositories from the service layer, a service constructor might look like this:
public DirectoryService(IUnitOfWork unitOfWork, ICountryRepository countryRepo, IProvinceRepository provinceRepo)
{
/* set member variables... */
}
The unit of work constructor might look like:
public UnitOfWork(IDbContext context)
{
_context = context;
}
And a repository constructor might look like:
CountryRepository(IDbContext context)
{
_context = context;
}
This solution makes the blind assumption that the Dependency injection is setting up the Unit of Work and Repositories to share the same IDbContext using instance per request. Is that really a safe assumption to make?
If you are using dependency injection with instance per request, the same IDbContext will be injected into multiple units of work. The unit of work is no longer atomic, is it? I might have pending changes in one service that are then committed in another service because the context is shared across multiple units of work.
To me it seems to make more sense to set up a IDbContextFactory and get a fresh database context with each unit of work.
public interface IDbContextFactory
{
IDbContext OpenContext();
}
public class UnitOfWork
{
private IDbContextFactory _factory;
private IDbContext _context;
UnitOfWork(IDbContextFactory factory)
{
_factory = factory;
}
internal IDbContext Context
{
get { return _context ?? (_context = _factory.OpenContext()); }
}
}
The problem then becomes, how do I make my Unit of Work implementation available to the injected repositories? I don't want to assume instance per request because then I'm right back in the same boat I started in.
The only thing I can think of is to follow Entity Framework's lead and make the repositories (IDbSet<T>) part of the unit of work (DbContext).
So then I might have units of work that look like this:
public class DirectoryUnitOfWork : IDirectoryUnitOfWork
{
private IDbContextFactory _factory;
private IDbContext _context;
public DirectoryUnitOfWork(IDbContextFactory factory)
{
_factory = factory;
}
protected IDbContext Context
{
get { return _context ?? (_context = _factory.OpenContext()); }
}
public ICountryRepository CountryRepository
{
get { return _countryRepo ?? (_countryRepo = new CountryRepository(Context)); }
}
public IProvinceRepository ProvinceRepository
{
get { return _provinceRepo ?? (_provinceRepo = new ProvinceRepository(Context)); }
}
void Commit()
{
Context.SaveChanges();
}
}
Then my Directory service starts to look like this
public class DirectoryService : IDirectoryService
{
private IDirectoryUnitOfWork _unitOfWork;
public DirectoryService(IDirectoryUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
public GetCountry(int id)
{
return _unitOfWork.CountryRepository.GetById(id);
}
public GetProvince(int id)
{
return _unitOfWork.ProvinceRepository.GetById(id);
}
public void AddProvince(Province province)
{
_unitOfWork.ProvinceRepository.Create(province);
Country country = GetCountry(province.CountryId);
country.NumberOfProvinces++; // Update aggregate count
_unitOfWork.Commit();
}
/* ... and so on ... */
}
It seems like a lot of work, but using this method leaves everything loosely coupled and unit testable. Am I missing an easier way, or is this a good way to do it if I am going to abstract away Entity Framework?
You should never abstract an ORM (itself an abstraction), but you should abstract the Persistence. The only UoW I'm using is a db transaction and that's a persistence detail. You don't need to use UoW and Repository together. You should think if you really need all this stuff.
Personally, I'm using the repository by default because Persistence is the last thing I do in an app. I don't care about patterns per se , I do care about decoupling my BL or the UI from DAL. Your upper layers (everything except DAL, which is the lowest layer from a dependency point of view) should always know about an abstraction, so that you can go as wild as you want in the DAL implementation.
One trick a lot of devs don't know is that design patterns (especially architectural ones) should be treated as a high level principle first and as a technical know-how second. Simply put, the thing that matters the most is the benefit a pattern is trying to achieve (the principle, the bigger picture), not its actual implementation (the "low level" details).
Ask yourself why should the BL know about a UoW in the first place. The BL only knows about an abstraction dealing with business objects. And you never work with the whole BL as once, you're always in a specific BL context. Your DirectoryService seems to be doing way to much for its own good. Updating stats doesn't look like it belongs to the same context as adding a new Province. Also why do you need UoW for queries?
One mistake I see a lot is devs rushing to write whatever code (with a design pattern attached) when they aren't doing the most important part: the design itself. When you have the improper design, problems appear and you start looking for workarounds. One of them is this UoW with Repository properties, which require a high layer like BL to know more than business concerns. Now the BL needs to know that you're using a UoW, a lower level pattern which is great for the DAL, not so great for the BL.
Btw, UoW never makes sense for quering as you're dealing with a 'read' situation, UoW is only for 'writes'. I don't mention EF or any ORM because they don't really matter, your BL service (Directory Service) is already corrupted by an infrastructural detail required by improper design. Note that sometimes you do need to compromise in order to implement a solution, but this is not the case.
Proper design means you know about your bounded context (yeah, DDD concept you can apply it regardless how much DDD you want to do) and don't put everything that might use the same data in one place. You have specific contexts for use cases and counting provinces (a presentation/reporting detail) is really a different use case than adding Province.
Adding the province and then publishing an event which signals to a handler to update stats is a more elegant, maintainable solution. No UoW required either.
Your code would look like this
public class DirectoryService : IDirectoryService
{
public DirectoryService(IProvinceRepository repo, IDispatchMessage bus)
{
//assign fields
}
/* other stuff */
//maybe province is an input model which is used by the service to create a business Province?
public void AddProvince(Province province)
{
_repo.Save(province);
_bus.Publish( new ProvinceCreated(province));
}
}
public class StatsUpdater:ISubscribeTo<ProvinceCreated> /* and other stat trigger events */
{
public void Handle(ProvinceCreated evnt)
{
//update stats here
}
}
In a way it simplifies things, in other way you might thing it complicates stuff. Actually, this is a maintainable approach, because the stats updater can subscribe to many events but the logic stays in one class only. And the DirectoryService does only the things that are assumed it does (what part of the name AddProvince hints you that the method also updates stats?).
In conclusion, you need to design the BL better before rushing to complicate your life with UoW, DbContext, Repositories as properties etc
or assumes that the DbContext used by the Unit of Work and Repositories is shared and should live for the entire HTTP request
This is clearly wrong. Assuming that the context is shared between the UoW and Repositories doesn't mean that the context lifetime should depend on the HTTP request. Rather - you can create new instances of the context and the UoW that use it whenever you want. This is only a convenience to have a default UoW that lives for the HTTP request but creating new, local units of work could be handy.
On the other hand, if repositories are exposed from the UoW:
public class UnitOfWork
{
...
public IUserRepository UserRepo
{
get { ... }
}
public IAccountRepository AccountRepo
{
get { ... }
}
then not sharing the same context between repos could have unexpected results:
UoW uow = ....
var u1 = uow.User.FirstOrDefault( u => u.ID == 5 );
var u2 = uow.Account.FirstOrDefault( a => a.ID_USER == 5 ).User;
You would definitely expect these two to return the same instance of the user of the id 5 and what's more, sharing the same context would mean that the second query could retrieve the user from the 1st level cache. On the other hand, two different contexts for two repos means that you get two different instances.
This also means that this would not be possible
var u1 = uow.User.FirstOrDefault( u => u.ID == 5 );
var a1 = uow.Account.FirstOrDefault( a => a.ID == 177 );
a1.User = u1; // oops!
as mixing entites from different contexts would just raise an exception. But the above scenario is a common one!
The conclusion from these observations is that you should share the context between repos. But, if you need a fresh instance, you just create a local, fresh instance of the context, inject it into the UoW, from where it gets injected into repos, and dispose it at will.

Is there anything wrong with having a few private methods exposing IQueryable<T> and all public methods exposing IEnumerable<T>?

I'm wondering if there is a better way to approach this problem. The objective is to reuse code.
Let’s say that I have a Linq-To-SQL datacontext and I've written a "repository style" class that wraps up a lot of the methods I need and exposes IQueryables. (so far, no problem).
Now, I'm building a service layer to sit on top of this repository, many of the service methods will be 1<->1 with repository methods, but some will not. I think a code sample will illustrate this better than words.
public class ServiceLayer
{
MyClassDataContext context;
IMyRepository rpo;
public ServiceLayer(MyClassDataContext ctx)
{
context = ctx;
rpo = new MyRepository(context);
}
private IQueryable<MyClass> ReadAllMyClass()
{
// pretend there is some complex business logic here
// and maybe some filtering of the current users access to "all"
// that I don't want to repeat in all of the public methods that access
// MyClass objects.
return rpo.ReadAllMyClass();
}
public IEnumerable<MyClass> GetAllMyClass()
{
// call private IQueryable so we can do attional "in-database" processing
return this.ReadAllMyClass();
}
public IEnumerable<MyClass> GetActiveMyClass()
{
// call private IQueryable so we can do attional "in-database" processing
// in this case a .Where() clause
return this.ReadAllMyClass().Where(mc => mc.IsActive.Equals(true));
}
#region "Something my class MAY need to do in the future"
private IQueryable<MyOtherTable> ReadAllMyOtherTable()
{
// there could be additional constrains which define
// "all" for the current user
return context.MyOtherTable;
}
public IEnumerable<MyOtherTable> GetAllMyOtherTable()
{
return this.ReadAllMyOtherTable();
}
public IEnumerable<MyOtherTable> GetInactiveOtherTable()
{
return this.ReadAllMyOtherTable.Where(ot => ot.IsActive.Equals(false));
}
#endregion
}
This particular case is not the best illustration, since I could just call the repository directly in the GetActiveMyClass method, but let’s presume that my private IQueryable does some extra processing and business logic that I don't want to replicate in both of my public methods.
Is that a bad way to attack an issue like this? I don't see it being so complex that it really warrants building a third class to sit between the repository and the service class, but I'd like to get your thoughts.
For the sake of argument, lets presume two additional things.
This service is going to be exposed through WCF and that each of these public IEnumerable methods will be calling a .Select(m => m.ToViewModel()) on each returned collection which will convert it to a POCO for serialization.
The service will eventually need to expose some context.SomeOtherTable which wont be wrapped into the repository.
I think it's a good model since you can create basic IQueryable private functions that can be used by the functions you are exposing publicly. This way your public methods do not need to recreate a lot of the common functionality your IQueryable methods perform and they can be extended as needed and deferring the execution while still hiding that functionality publicly.
An example like how to get X out of some table which may take a lot of logic that you don't need in it's raw form. You then have that as a private method, as you do in your example, and then the public method adds the finalizing criteria or queries to generate a useable set of data which could differ from function to function. Why keep reinventing the wheel over and over... just create the basic design (which you IQueryable does) and drop on the tread pattern that is required as needed (your public IEnumerable does) :)
+1 for a good design IMO.

Loading Subrecords in the Repository Pattern

Using LINQ TO SQL as the underpinning of a Repository-based solution. My implementation is as follows:
IRepository
FindAll
FindByID
Insert
Update
Delete
Then I have extension methods that are used to query the results as such:
WhereSomethingEqualsTrue() ...
My question is as follows:
My Users repository has N roles. Do I create a Roles repository to manage Roles? I worry I'll end up creating dozens of Repositories (1 per table almost except for Join tables) if I go this route. Is a Repository per Table common?
If you are building your Repository to be specific to one Entity (table), such that each Entity has the list of methods in your IRepository interface that you listed above, then what you are really doing is an implementation of the Active Record pattern.
You should definitely not have one Repository per table. You need to identify the Aggregates in your domain model, and the operations that you want to perform on them. Users and Roles are usually tightly related, and generally your application would be performing operations with them in tandem - this calls for a single repository, centered around the User and it's set of closely related entities.
I'm guessing from your post that you've seen this example. The problem with this example is that all the repositories are sharing the same CRUD functionality at the base level, but he doesn't go beyond this and implement any of the domain functions. All the repositories in that example look the same - but in reality, real repositories don't all look the same (although they should still be interfaced), there will be specific domain operations associated with each one.
Your repository domain operations should look more like:
userRepository.FindRolesByUserId(int userID)
userRepository.AddUserToRole(int userID)
userRepository.FindAllUsers()
userRepository.FindAllRoles()
userRepository.GetUserSettings(int userID)
etc...
These are specific operations that your application wants to perform on the underlying data, and the Repository should provide that. Think of it as the Repository represents the set of atomic operations that you would perform on the domain. If you choose to share some functionality through a generic repository, and extend specific repositories with extension methods, that's one approach that may work just fine for your app.
A good rule of thumb is that it should be rare for your application to need to instantiate multiple repositories to complete an operation. The need does arise, but if every event handler in your app is juggling six repositories just to take the user's input and correctly instantiate the entities that the input represents, then you probably have design problems.
Is a Repository per Table common?
No, but you can still have several repositiories. You should build a repository around an aggregate.
Also, you might be able to abstract some functionality from all the repositories... and, since you are using Linq-to-Sql, you probably can...
You can implement a base repository which in a generic way implements all this common functionality.
The following example serves only to prove this point. It probably needs a lot of improvement...
interface IRepository<T> : IDisposable where T : class
{
IEnumerable<T> FindAll(Func<T, bool> predicate);
T FindByID(Func<T, bool> predicate);
void Insert(T e);
void Update(T e);
void Delete(T e);
}
class MyRepository<T> : IRepository<T> where T : class
{
public DataContext Context { get; set; }
public MyRepository(DataContext context)
{
Context = Context;
}
public IEnumerable<T> FindAll(Func<T,bool> predicate)
{
return Context.GetTable<T>().Where(predicate);
}
public T FindByID(Func<T,bool> predicate)
{
return Context.GetTable<T>().SingleOrDefault(predicate);
}
public void Insert(T e)
{
Context.GetTable<T>().InsertOnSubmit(e);
}
public void Update(T e)
{
throw new NotImplementedException();
}
public void Delete(T e)
{
Context.GetTable<T>().DeleteOnSubmit(e);
}
public void Dispose()
{
Context.Dispose();
}
}
To me the repository pattern is about putting a thin wrapper around your data access methodology. LINQ to SQL in your case, but NHibernate, hand-rolled in others. What I've found myself doing is create a repository-per-table for that is extremely simple (like bruno lists and you already have). That is responsible for finding things and doing CRUD operations.
But then I have a service level that deals more with aggregate roots, as Johannes mentions. I would have a UserService with a method like GetExistingUser(int id). This would internally call the UserRepository.GetById() method to retrieve the user. If your business process requires the user class returned by GetExistingUser() to pretty much always need the User.IsInRoles() property to be filled, then simply have the UserService depend upon both the UserRepository and RoleRepository. In pseudo code it could look something like this:
public class UserService
{
public UserService(IUserRepository userRep, IRoleRepository roleRep) {...}
public User GetById(int id)
{
User user = _userService.GetById(id);
user.Roles = _roleService.FindByUser(id);
return user;
}
The userRep and roleRep would be constructed with your LINQ to SQL bits something like this:
public class UserRep : IUserRepository
{
public UserRep(string connectionStringName)
{
// user the conn when building your datacontext
}
public User GetById(int id)
{
var context = new DataContext(_conString);
// obviously typing this freeform but you get the idea...
var user = // linq stuff
return user;
}
public IQueryable<User> FindAll()
{
var context = // ... same pattern, delayed execution
}
}
Personally I would make the repository classes internally scoped and have the UserService and other XXXXXService classes public so keep your consumers of the service API honest. So again I see repositories as more closely linked to the act of talking to a datastore, but your service layer being more closely aligned to the needs of your business process.
I've often found myself really overthinking the flexibility of Linq to Objects and all that stuff and using IQuerable et al instead of just building service methods that spit out what I actually need. User LINQ where appropriate but don't try to make the respository do everything.
public IList<User> ActiveUsersInRole(Role role)
{
var users = _userRep.FindAll(); // IQueryable<User>() - delayed execution;
var activeUsersInRole = from users u where u.IsActive = true && u.Role.Contains(role);
// I can't remember any linq and i'm type pseudocode, but
// again the point is that the service is presenting a simple
// interface and delegating responsibility to
// the repository with it's simple methods.
return activeUsersInRole;
}
So, that was a bit rambling. Not sure if I really helped any, but my advise is to avoid getting too fancy with extension methods, and just add another layer to keep each of the moving parts pretty simple. Works for me.
If we write our repository layer as detailed as Womp suggests, what do we put in our service layer. Do we have to repeat same method calls, which would mostly consists of calls to corresponding repository method, for use in our controllers or codebehinds? This assumes that you have a service layer, where you write your validation, caching, workflow, authentication/authorization code, right? Or am I way off base?

Categories