Is Db access from my Services Layer a bad thing? - c#

My last app implemented UoW, DI, IoC, Repository Pattern, Factories, all sorts of stuff that seemed neat, but made maintenance and debugging a pain.
I'm taking the opposite approach with my most recent app - no DI, no IoC, no UoW, just MVC, Services Layer, and DB. I'm probably thinking about Repository Pattern all wrong, but the reading that I've done suggests that it's responsible only for Db access, and not Business logic, to keep the two concerns separated.
In implementing a repository pattern, I feel like I'm just duplicating so much of my Service layer. For example, in my UserService class, I have the following:
public void UpdateAboutMe(AboutMeDto request)
{
using (var db = CreateContext())
{
var user = db.Users.FirstOrDefault(s => s.Username.Equals(request.Username, StringComparison.OrdinalIgnoreCase));
if (user != null)
{
user.AboutMe = request.AboutMe;
SaveChanges(db);
}
else
{
throw new InvalidDataException("Null User");
}
}
}
This way, the Service grabs the object, updates a single field, and commits the changes to the DB, and disposes the context.
In my UserService, I have other methods like this:
GetUserByUserName
GetUserById
GetUsersWithChildEntities
GetUsersWithoutChildEntities (faster than the former, right?)
UpdateUserThumbnail
UpdateUserBio
UpdateUserInterests
Wouldn't every one of these need a corresponding Repo method?
If I implement a repository method, the above service might look like this:
public void UpdateAboutMe(AboutMeDto request)
{
return _userRepository.UpdateAboutMe(request);
}
Which seems cleaner, but not a lot cleaner since I'm just moving stuff around - and if I decide to change my one of my Get methods to include some child entity, I now have to create another method in the Repo, update the Interface, and update the Service method, instead of just doing it directly from my service method.
I'm basically interested in learning whether or not I should implement Repository Pattern, based on the limited understanding I've demonstrated above. It seems like it's either add a vertical layer of complexity to your app, or just make your service layer a little beefier.
IMO - with EF lazy loading and per-field updates - Repository Pattern seems like so much more overhead.
And, I'm not huge on TDD in this case, so I'd like to keep testability out of the equation if possible.

Patterns exist to solve problems. If the way the pattern solves the problem introduces others that aren't acceptable in your environment, then either you are doing it wrong or you just need to go down a different path.
Along with this, just because something is a pattern doesn't mean you should blindly use it. There are many "patterns" that I consider to be pure garbage due to introducing large swaths of code for relatively little gain.
I'm not sure why you have a method call to update a single field on a single record. That seems to make things a bit difficult and certainly can cause lots of DB queries to fire off when just one would do, essentially undermining performance for no gain.
Two examples:
GetUser(String userName, Int32 id, Boolean withEntities);
or
GetUser(String userName, Boolean withEntities);
GetUser(Int32 id, Boolean withEntities);
The first one combines your common ways of acquiring a specific user account. The second one duplicates code, but splits it out. Later you might decide to add a GetUser(String email, Boolean withEntities) at some point.
The various UpdateUser... methods you have I'd roll into one. Passing a full User object into it and letting the one method update the entire thing. There are very very few circumstances where I'd have methods update just a single field.

If you aren't interested in TDD, IoC/DI, or reuseability, there's no need to have excess layers. Each layer has a purpose, but if you do not have that purpose you do not need that layer.
However, it will become more difficult to rewrite things once people start dying during a server outage.

Related

Using CQRS with repositories

If I understand correctly CQRS is about dividing write and read responsibilities. So I can use repositories in my write model, for example var user = repository.GetUserById(); - this will get the user by id and then repository.UpdateUser(user); will update the user with changed properties. In the read model we can construct more complex DTO's:
public class UsersReadModel
{
private IMyContext context;
public UsersReadModel(IMyContext context)
{
this.context = context;
}
public ComplexUserDTO GetComplexUser(ISelectQuery query)
{
ComplexUserDTO user = new ComplexUserDTO();
// get all user properties, GetUser by id
user.UserDTO = context.Users.Where(d => d.UserId == query.UserId).ProjectTo<UserDTO>().FirstOrDefault();
//here I don't need everything from PoliciesTable, I just need two columns, so I use anonymous object
var policieObject = context.Policies.Where(f => f.BasePolicyId == query.PolicyId).Select(s => new { s.PoliciesNames, s.Clients.Select(d => d.ClientNames).ToList() }).FirstOrDefault();
user.PoliciesNames = policieObject.PoliciesNames;
user.ClientsNames = policieObject.ClientsNames;
return user;
}
}
So in my Write model, I get user by id from my repository, because i don't need to map it to DTO, and in my read model I use GetUser by id, but I map it to DTO, because I need it in that way. Isn't this code repeat(if I want to change getting user by id i'll have to change it in both places)? Can I use repositories in my read model? In this case I'll have to use both repositories and context(for the anonymous object, and selecting part of table columns) in UsersReadModel.
If your domain is very simple then the Write and the Read will be very similar and a lot of cod duplication will occur. In fact, this works in reverse as well, if your Write model is very similar to the Read model then you could implement them as CRUD and you don't necessarily need CQRS.
Can I use repositories in my read model?
You can have anything you want on the Read side; the two sides are separated from many points of view.
In CQRS there are many cases when code duplication occurs. Don't be afraid of that. You could extract that in shared classes.
P.S.
You should have a Read model for every use case, not for every Write model. If you have a 1:1 correspondence from Write to Read then this could also means that you should have implemented this using CRUD.
P.S. I like to use CQRS even if the domain is simple as I like to have very optimized Read models (different persistence type, no JOINS, custom data sharding etc).
There are a few things to look at here. From your description, it doesn't sound like there is a separation between the read and write models. Remember, they have very different purposes.
CQRS leans heavily on domain-driven design principles. A key principle is the encapsulation of your domain objects.
As a result, you wouldn't expect a domain object to have 'properties' on it (especially not setters). It may have ID for example but not much else. This is becuase it's role is to protect invariants within its self. Not something you can do easily if you have setters.
I would also argue that a domain object shouldn't really have getters except for id. If you have a good read model there is little need for them and may encourage incorrect use of the object. There are times when this idea can be relaxed a little. Although I can't think of one right now.
As a result, a repository for a domain object can be very simple. GetById and Save (unless you are using event sourcing but that's another topic).
The Read model, on the other hand, should be shaped to serve the UI. Each model is likely to have a mix of data from various sources. For example, you are likely to want to see a users details in context or their activities or orders or value to the company or whatever the purpose of the application is.
This explanation of the typical structure of a CQRS application may be helpful: CQRS + Event Sourcing - A Step by Step Overview
And this may give you some insight into creating domain objects: Aggregate Root - How to Build One for CQRS and Event Sourcing
Hope this helps.
If I understand correctly CQRS is about dividing write and read responsibilities.
Closer to say that it is about having data models that are designed for the use cases that they support.
We have Truth, and that truth has multiple representations.
The trick is that the representations don't need to be coupled in time -- we can update the "book of record" representation now, and the representations we use to support queries eventually.
Can I use repositories in my read model?
Absolutely. There's no magic.
Udi Dahan would probably suggest that you be thinking about different repositories, or perhaps more precisely methods on your repositories that provide different explicit representations of the read model depending on what you are doing. Each method loads the representation that you need for that particular use case.

Business logic integrated into entity framework

I've read some of the articles on BL, but the methodology seems counter intuitive to me. It seems to break up normal OOP principles. Here's an very simplified example: A client table contains the birthdate and gender of each client. A life expectancy table contains the clientId, age, and probability of survivorship to that age.
Wouldn't basic OOP principles call for methods to be integrated into the entity? E.g. the calculateSPTable() method in the client class.
class client {
int clientId;
int age;
bool male;
list<surviveProb> lifeExpectancy;
void calculateLifeExpectancy(); // calculates lifeExpectancy
}
class surviveProb {
int surviveProbId;
int clientId;
int age;
double probability;
}
Yet the methodologies today seem to suggest such operations must be in a separate layer and a separate class. Methods operating on entities should not be included in the entity framework entities. This seems counter intuitive. I really want to put methods into EF entities. Is this going to lead to problems? What am I missing here?
After some research I now use some patterns that I think are good for maintenance porpoises and understanding the application.
Let's say you want to register an account.
In the controller, I would have an AddAccountViewModel that only exposes the minimum properties to a user. No worries about him injecting something bad in an unexpected property. Now, using dependency injection, I would call a Facade. Let's say _accountsFacade.RegisterAccount and I would pass the View Model as a parameter.
Inside this method in the facade, I would do the mapping from the View Model to the Model and this Facade would be responsible for doing everything that needed to be done so the account could be created. In my opinion, here is where all the business logic goes. In this Facade, using dependency injection again, I use a unit of Work and add and edit entities to the context. _unitOfWork.AccountRepository.Add(account)
You see? Controllers only "route" the application, facades handle business, unit of work handles the context, the repository only communicates with the data base... And the model only expose properties.
This makes the mapping faster, as stated, and it separate concerns. Sometimes, the logic of adding an account may involve handling different objects that shouldn't be used inside the account object,
I hope you can understand what I want to explain, as my English is not so great.
Was it helpful?

Service behaviour in Entity - how to avoid service injection into entity?

I have an entity structure as follows:
IManager: IDeletable
{
IEnumerable<IFund> Funds {get;}
IFailureNotification Delete();
}
IFund : IDeletable
{
IEnumerable<IFundClass> FundClasses
IFailureNotification Delete();
}
IFundClass: IDeletable, IInvestable
{
IFailureNotification Delete();
}
And I have a service which takes an IDeletable and calls Delete on it. Depending on the return value it then either commits the transaction or rolls it back. I'm using NHibernate to persist the classes so can't put RI in the DB and catch the exception (which I wouldn't like anyway).
This is a classic case for polymorphism and the Manager loops through its Funds and deletes them before deleting itself, the Fund in turn delete the FundClasses before deleting themselves, so the service can just take any entity implementing IDeletable and know that the deletion will perform the appropriate actions at all levels.
Here's the problem: The fund classes need to find if they're being used in a completely separate context using the IInvestable interface which they don't know anything about. This requires a service - the IInvestmentCalculationService.
Obviously I don't want to inject the InvestmentCalculationService into the fund class entity constructor and I don't want to inject it into the delete method as this is on Funds and Managers as well as many other classes so doesn't make any sense - also means that as soon as we have more requirements we have to change the delete methods on everything.
I'm a bit tempted by the Domain Events model here: http://www.udidahan.com/2009/06/14/domain-events-salvation/ but I'm not confident that it's right as I'm trying to get data back from the triggered event handler - which would work but smells a little bit wrong, and all the examples only show fire and forget situations.
Does anyone have any suggestions?
Thanks to all for their help, I was really impressed by the audience I attracted! I especially liked mcintyre's philosophy and it's genuinely affected my thinking since. In this case though we went for double dispatch. Feels a little more stable.
Cheers
"Obviously I don't want to inject the InvestmentCalculationService".
Its the word 'obviously' that I don't like. I still haven't felt compelled by the results from googling "injecting services into entities". The top posts on the subject boil down to "it doesn't feel right and you can use domain events/double dispatch to do it anyway so don't do it".
I personally think it's fine to inject services into entities and reckon you should stop worrying about it and do it. Maybe don't inject the whole InvestmentCalculationService, but inject the BitsOfInvestmentCalculationServiceThatINeedToKnowAboutService if you feel the entity doesn't need to have access to the whole thing.
Domain events is no good in your situation unless you add a return value (which basically makes it into a dressed up service locator) and with double dispatch, the thing you are injecting has to come from somewhere higher up the call stack - probably an injected value to the entry point class which in all likeliness doesn't use that dependency.
Just inject the InvestmentCalculationService into the entity and get on with your life.
One thing we've done in situations like these is have the Delete not do the actual deletion, but instead use a collecting parameter for things to delete. The Delete() method would register itself and any other objects, which then get replayed by another service.
How about having an interface
public interface ICanBeDeleted<T>
{
bool CanBeDeleted(T itemToBeDeleted);
}
Before actually deleting ask your container for all implementations of this interface, invoke the CanBeDeleted function and if any return false then do not delete. Your InvestmentCalculationService would implement ICanBeDeleted<FundClass> and register with the container.

ASP MVC: Should services return IQueryable's?

What do you think? should your DAO return an IQueryable to use it in your controllers?
No. Your controllers shouldn't be handling any complex logic at all. Keep them slim; the Model (not DAO) should hand the Controller back everything it needs to pass onto the View.
Seeing queries (or even queryables) in a Controller class is something I would consider to be a code smell.
At the moment, it sounds attractive, but really isn't.
I love passing IQueryable into my controllers because I don't have to create lame paging and sorting methods in every single DAO method and interface throughout the lifetime of my apps development.
GetCustomersByLastname( string lastname )
Quickly Becomes
GetCustomersByLastname( string lastname, string sortcolumn, int pagesize, int page )
Again and again and again and again. Bleck!
With IQueryable you can take implement paging and sorting in orthogonal ways such as taking advantage of the IPagedList project. Returning IQueryable also give you easy access to total object .Count() without more perversion of your data layer.
#Robert s argument of IQueryable equals fat controllers is very shaky. A Fat controller would be similar to the bloated .aspx.cs pages of yore. If all your doing is connecting to your DAL and then shipping the results off your don't gain "fatness" from your query technique, you gain it from shoving lots of logic inside inside a single class. You do not get a Fat Controller because of your data access methods unless you start rolling logging, notifications, and other orthogonal concerns inside.
public ActionResult Detail( string searchTerm )
{
var model = MyDAL.MyObjects( searchTerm );
}
vs:
public ActionResult Detail( string searchTerm )
{
var model = MyDAL.MyObjects.Where( x => x.Name == searchTerm );
}
I don't see a compelling difference.
#Mark Seemann 's answer is equally shaky. Sure, you may change your entire data layer in the middle of a project but that is going to be a complex disaster no matter how abstracted you are. The example he uses is switching from Linq2Sql to Windows Azure's table storage. RDBMS to Key/Value store? And the pain point is your Repository implementation? Going from RDBMS to a Key/Value store is going to be some craziness thats going to be horrible no matter what.
Mark also brings up Domain Driven Design in his argument. Is that the type of system your building. Is there enough "Domain" rather than pure CRUD scenarios that make this approach valuable? If not then why bother?
Using and LINQ and the IQueryable interface gives you less of the pain of switching data layers anyway. If your switching between ORMs that support LINQ and IQueryableProvider ( I think thats the name ) than only the downstream code cares about that change. Your controllers would stay the same switching between from most ORMs on the market now.
If you follow the "fat models, skinny controllers" paradigm then no.
See this post on the Fat Controller anti-pattern.

How much knowledge of your domain should your repository layer have?

When working on a repository i generaly try to keep the method pretty generic, but this can sometimes lead to calling longer methods, or creating more specificly named methods at the service layer. My question is, how much knowledge of your domain should your a resitory layer have?
For example, I currently have a method as follows:
public User GetUniqueByRoleAndRoleProperty<TRole>(string propertyName, object propertyValue)
{
...
}
Which I use to pull back users with a specific role and property, but would it be giving the repository too much knowledge to have a method such as:
public User GetArtistBySlug(string slug)
{
...
}
It should have enough knowledge to do its work and no more. It's fine to have a lookup for artists by slug if "slug" is an attribute of the "artist" record, because the layer knows that already. If the assignment of slugs to artists follows complex, intricate rules (think heraldry, or something like that), then the repository should not implement those, except if you absolutely have to use clever optimizations that only work on this level, e.g. special database query constructions.

Categories