Trying to make a really simple repository and service layer pattern here. (.NET 4, C#, LINQ, although this question is partially language-agnostic). Note: this is just R&D.
My goal is to minimize the amount of method definitions in my service layer.
Here's my Repository Contract:
interface IFooRepository
{
IEnumerable<Foo> Find();
void Insert(Foo foo);
void Update(Foo foo);
void Delete(Foo foo);
}
Nothing new there.
Now, here's what im (trying) to have in my Service Contract:
interface IFooDataService
{
public IEnumerable<Foo> Find(FooSearchArgs searchArgs);
}
Essentially, any particular "Foo" has many properties (id, name, etc), which i would like to be able to search upon.
So, i dont want to have 1x Find method for each different property, i just want one - that way when i create extra properties i dont have to modify the contracts.
The "FooSearchArgs" is just a simple POCO with all the different "Foo" properties it.
So, that's what im trying to do, here's my questions:
Is this poor design? If so, what are the alternatives?
How can i implement this filtering in the service layer? Would i have to check what properties of "FooSearchArgs" are set, then keep filtering down? (if this, then query.where, if this, query.where, etc) Anyone have an idea of a clever LINQ IEnumerable extension method to do this? (ie repository.WhereMeetsSearchCriteria(fooSearchArgs))
Appreciate the help.
We use something very similar. One thing you need to decide on is if you are going to expose IQueryable outside of the repository. Your find method returns IEnumerable which could be the IQueryable returned from your when clause.
The advantage of returning the IQueryable is that you can further refine your criteria up outside of your repository layer.
repository.Find(predicate).Where(x => x.SomeValue == 1);
The expression will only be compiled when you come to use the returned data and here in lies the disadvantage. Because you only hit the database when you actually come to use the results you could end up trying to call the database after your session (nhibernate) or connections have been closed.
My personal preference is to use the specification pattern where you pass your find method an ISpecification object is used to do the query.
public interface ISpecification<TCandidate>
{
IQueryable<TCandidate> GetSatisfyingElements(IQueryable<TCandidate> source);
}
public class TestSpecification : ISpecification<TestEntity>
{
public IQueryable<TestEntity> GetSatisfyingElements(IQueryable<TestEntity> source)
{
return source.Where(x => x.SomeValue == 2);
}
}
public class ActiveRecordFooRepository: IFooRepository
{
...
public IEnumerable<TEntity> Find<TEntity>(ISpecification<TEntity> specification) where TEntity : class
{
...
return specification.GetSatisfyingElements(ActiveRecordLinq.AsQueryable<TEntity>()).ToArray();
...
}
public TEntity FindFirst<TEntity>(ISpecification<TEntity> specification) where TEntity : class
{
return specification.GetSatisfyingElements(ActiveRecordLinq.AsQueryable<TEntity>()).First();
}
}
After the query is run the repository calls ToArray or ToList on the resulting IQueryable returned from the specification so that the query is evaluated there and then. Whilst this may seem less flexible than exposing IQueryable it comes with several advantages.
Queries are executed straight away and prevents a call to the database being made after sessions have closed.
Because your queries are now bundled into specifications they are unit testable.
Specifications are reusable meaning you don't have code duplication when trying to run similar queries and any bugs in the queries only need to be fixed in one place.
With the right kind of implementation you can also chain your specifications together.
repository.Find(
firstSpecification
.And(secondSpecification)
.Or(thirdSpecification)
.OrderBy(orderBySpecification));
Is passing a Func as a parameter to your service layer's Find method, instead of the FooSearchArgs, an option? Enumerables have a Where method (linq) that takes a Func as a parameter, so you could use it to filter the results.
Related
I have a DAL layer based on the Repository pattern, which means I have some BaseRepository with the basic generic implementation.
I also have the specified classes which use this BaseRepository by inheritance.
Now I need to restrict the filtering based on some userId condition.
I can't do it excplicitly, I must do it implicitely and this is the question.
So for the explicit filtering, I could something like this:
Change the method in the Base class:
public T GetById(object id, Func<T, bool> predicate)
{
return _dbSet.Where(predicate).Find(id);
}
And then do something like this in the class which uses it:
public User GetById(Guid id)
{
return userRepository.Where(p=>...).GetById(id);
}
But this restriction is too obvious for the developers.
Is there a way to make a restriction which is not or at least not so much obvious?
What you are trying to do is not possible, at least not by only using code. The filtering has to explicitly happen at some point, and the best you could possibly do is obfuscate it. But the developer will be able to still find it.
One option you do have is to create a view in Sql Server which is performing the filtering and just use linq to query that view. The only potential downside to doing that is that the view is read only.
Let’s say I have some DDD service that requires some IEnumerable<Foo> to perform some calculations. I came up with two designs:
Abstract the data access with an IFooRepository interface, which is quite typical
public class FooService
{
private readonly IFooRepository _fooRepository;
public FooService(IFooRepository fooRepository)
=> _fooRepository = fooRepository;
public int Calculate()
{
var fooModels = _fooRepository.GetAll();
return fooModels.Sum(f => f.Bar);
}
}
Do not rely on the IFooRepository abstraction and inject IEnumerable<Foo> directly
public class FooService
{
private readonly IEnumerable<Foo> _foos;
public FooService(IEnumerable<Foo> foos)
=> _foos = foos;
public int Calculate()
=> _foos.Sum(f => f.Bar);
}
This second design seems better in my opinion as FooService now does not care where the data is coming from and Calculate becomes pure domain logic (ignoring the fact that IEnumerable may come from an impure source).
Another argument for using the second design is that when IFooRepository performs asynchronous IO over the network, usually it will be desirable to use async-await like:
public class AsyncDbFooRepository : IFooRepository
{
public async Task<IEnumerable<Foo>> GetAll()
{
// Asynchronously fetch results from database
}
}
But as you need to async all the way down, FooService is now forced to change its signature to async Task<int> Calculate(). This seems to violate the dependency inversion principle.
However, there are also issues with the second design. First of all, you have to rely on the DI container (using Simple Injector as an example here) or the composition root to resolve the data access code like:
public class CompositionRoot
{
public void ComposeDependencies()
{
container.Register<IFooRepository, AsyncDbFooRepository>(Lifestyle.Scoped);
// Not sure if the syntax is right, but it demonstrates the concept
container.Register<FooService>(async () => new FooService(await GetFoos(container)));
}
private async Task<IEnumerable<Foo>> GetFoos(Container container)
{
var fooRepository = container.GetInstance<IFooRepository>();
return await fooRepository.GetAll();
}
}
Also in my specific scenario, AsyncDbFooRepository requires some sort of runtime parameter to construct, and that means you need an abstract factory to construct AsyncDbFooRepository.
With the abstract factory, now I have to manage the life cycles of all dependencies under AsyncDbFooRepository (the object graph under AsyncDbFooRepository is not trivial). I have a hunch that I am using DI incorrectly if I opt for the second design.
In summary, my questions are:
Am I using DI incorrectly in my second design?
How can I compose my dependencies satisfactorily for my second design?
One aspect of async/await is that it by definition needs to applied "all the way down" as you rightfully state. You however can't prevent the use of Task<T> when injecting an IEnumerable<T>, as you suggest in your second option. You will have to inject a Task<IEnumerable<T>> into constructors to ensure data is retrieved asynchronously. When injecting an IEnumerable<T> it either means that your thread gets blocked when the collection is enumerated -or- all data must be loaded during object graph construction.
Loading data during object graph construction however is problematic, because of the reasons I explained here. Besides that, since we're dealing with collections of data here, it means that all data must be fetched from the database on each request, even though not all data might be required or even used. This might cause quite a performance penalty.
Am I using DI incorrectly in my second design?
That's hard to say. An IEnumerable<T> is a stream, so you could consider it a factory, which means that injecting an IEnumerable<T> does not require the runtime data to be loaded during object construction. As long as that condition is met, injecting an IEnumerable<T> could be fine, but still makes it impossible to make the system asynchronous.
However, when injecting an IEnumerable<T> you might end up with ambiguity, because it might not be very clear what it means to be injecting an IEnumerable<T>. Is that collection a stream that is lazily evaluated or not? Does it contain all elements of T. Is T runtime data or a service?
To prevent this confusion, moving the loading of this runtime information behind an abstraction is typically the best thing to do. To make your life easier, you could make the repository abstraction generic as well:
public interface IRepository<T> where T : Entity
{
Task<IEnumerable<T>> GetAll();
}
This allows you to have one generic implementation and make one single registration for all entities in the system.
How can I compose my dependencies satisfactorily for my second design?
You can't. To be able to do this, your DI container must be able to resolve object graphs asynchronously. For instance, it requires the following API:
Task<T> GetInstanceAsync<T>()
But Simple Injection doesn't have such API, and neither does any other existing DI Container and that's for good reason. The reason is that object construction must be simple, fast and reliable and you lose that when doing I/O during object graph construction.
So not only is your second design undesirable, it is impossible to do so when data is loaded during object construction, without breaking the asynchonicity of the system and causing threads to block while using a DI container.
I try as much as possible (until now I've succeded every time) to not inject any service that do IO in my domain models as I like to keep them pure with no side effects.
That being said the second solution seems better but there is a problem with the signature of the method public int Calculate(): it uses some hidden data to perform the calculation, so it is not explicit. In cases like this I like to pass the transient input data as input parameter directly to the method like this:
public int Calculate(IEnumerable<Foo> foos)
In this way it is very clear what the method needs and what it returns (based on the combination of class name and method name).
I've seen various blog posts (and much conflicting advice) about the repository pattern, and so I'll start by saying that the code below is probably not following the repository pattern in many people's opinion. However, it's a common-enough implementation, and whether it adheres to Fowler's original definition or not, I'm still interested in understanding more about how this implementation is used in practice.
Suppose I have a project where data access is abstracted via an interface such as the one below, which provides basic CRUD operations.
public interface IGenericRepository<T>
{
void Add(T entity);
void Remove(T entity);
void Update(T entity);
IEnumerable<T> Fetch(Expression<Func<T,bool>> where);
}
Further suppose that I have a service layer built atop that, for example:
public class FooService
{
private IGenericRepository<Foo> _fooRespository;
...
public IEnumerable<Foo> GetBrightlyColoredFoos()
{
return _fooRepository.Fetch(f => f.Color == "pink" || f.Color == "yellow");
}
}
Now suppose that I now need to know how many brightly colored Foos there are, without actually wanting to enumerate them. Ideally, I want to implement a CountBrightlyColoredFoos() method in my service, but the repository implementation gives me no way to achieve that other than by fetching them all and counting them - which is potentially very inefficient.
I could extend the repository to add a Count() method, but what about other aggregate functions that I might need, such as Min() or Max(), or Sum(), or... you get the idea.
Likewise, what if I wanted to get a list of the distinct Foo colors (SELECT DISTINCT). Again, the simple repository provides no way to do that sort of thing either.
Keeping the repository simple to make it easy to test/mock is very laudable, but how do you then address these requirements? Surely there are only two ways to go - a more complex repository, or a "back-door" for the service layer to use that bypasses the repository (and thus defeats its purpose).
I would say you need to change your design. What you want to do is have one "main" generic repository that has your basic CRUD, but also smaller repositories for each entity. You will then just have to draw a line on where to place certain operations (like sum, count, max, etc.) Most likely not all your entities are going to have to get counted, summed, etc. and most of the time you won't be able to add a generic version that applies to all entities for aggregate functions.
Base Repository:
public abstract class BaseRep<T> : IBaseRep<T> where T : class
{
//basic CRUD
}
Foo Repository:
public class FooRep : BaseRep<Foo>, IFooRep
{
//foo specific functions
}
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.
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?