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.
Related
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 am trying to Implement a Generic Repository with Linq To SQL. My problem lies in that some of my underlying tables have int ID's and some Guid ID's. How would I account for that?
public T GetById(int id)
{
return this._context.GetTable<T>().Single(x => x.ID.Equals(id));
}
Add another generic parameter to the repository interface.
public interface IRepo<TType, PKType>
{
TType GetById(PKType id);
}
Then implement it.
public class CustomerRepo : IRepo<Customer, Guid>
{
public Customer GetById(Guid id)
{
// code to get from repo
}
}
Well, first - A GetById makes no sense to start, ever heard of LINQ? Let the USER decide. Get if anything.
Second, even IF you insist on that, there is still generics.
GetById (T id)
would go that far, you can have more than one Type on a generic, but you assume then "id" as name, which requires an interface.
As fact, you have more grave problems, as
GetTable().Single(x => x.ID.Equals(id));
is likely blowing in the compiler in this case, there is no limitation that requires T to have an id field. As such, you an not use it in a generic method.
THAT SAID - as I said in the beginning, by stripping the user from the power of a signficant part of the language (linq) you are basically creating yet another antipattern implementation of a generic bad repository.
With StructureMap, can one inject instances based on their name by convention, like so:
Ctor:
public HomeController(IQuery getItemByProductNumberQuery, IQuery getCustomerById)
StructureMap config:
x.For<IQuery>().Add<GetItemByProductNumberQuery>().Named("getItemByProductNumberQuery");
x.For<IQuery>().Add<GetCustomerById>().Named("getCustomerById");
I'm working with legacy code, so changing the DI container is a huge undertaking, but it would be interesting to know about other containers' solution to the problem at hand as well.
It seems to me that you are missing an abstraction in your code base. Under normal circumstances, a service (IQuery in your case) should be unambiguous, which isn't the case in your situation. Identifying them by the argument name is often error prone and leads to a DI configuration that is hard to maintain. This doesn't always have to be this way (as can be seen in this example), but it probably is in your case.
To solve this, make your IQuery interface generic:
public interface IQuery<TParameters, TResult>
{
TResult Handle(TParameters parameters);
}
This allows you to register all implementations of this interface by their closed generic representation, and allow your control to depend on this closed generic representation:
public HomeController(
IQuery<GetItemByProductNumberParameters, Item> getItemQuery,
IQuery<GetCustomerByIdParameters, Customer> getCustomerById)
As you can see, each query defines a 'XXXParameters' object. This is a DTO that contains all parameters needed to run the query. The code in your HomeController might look like this:
public View Item(int productNumber)
{
var parameters = new GetItemByProductNumberParameters
{
ProductNumber = productNumber,
// other parameters here
};
Item item = this.getItemQuery.Handle(parameters);
return this.View(item);
}
It might be a bit difficult to batch register all IQuery<TParameter, TResult> implementations in one go with StructureMap, but this SO question might help. And if not, using another DI container might yield better results.
You can find more information about why you want to model your queries this way in this article: Meanwhile… on the query side of my architecture.
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.