Business logic integrated into entity framework - c#

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?

Related

According to DDD do i need additional repository and model

According to DDD for each aggregate i have repository. Let's take an example:
Client (model aggregate) > ClientRepository
Visit (model aggregate) > VisitRepository
Now phisicly i have association table in database which connects Client and Visit because clients could have many visists.
The question is: Should i create separated model like: ClientVisit which also would be an aggregate:
public class ClientVisit
{
int clientId;
int visitId;
}
Also s repository like ClientVisitRepository which could reference/use ClientRepository and VisitRepository.
Or is it enough to stick with e.g CLientRepository and get data from there without additionality model and repository
Modification to the post:
Instead of Visit (wrong example) - let's replace by Car therefore each client can have many cars. We would have also unique transactionNumber so:
Client (model aggregate) > ClientRepository
Car (model aggregate) > CarRepository
Should then i then create aggregate such as:
public class ClientCar
{
int clientId;
int visitId;
int transactionNumber;
}
and ClientCarRepository?
No, don't use a different repository for each entity or aggregate. You are not applying DDD completely in your modelling. You have to focus on the Ubiquitous language. Let me explain.
Repositories are meant to be nothing more than serializers and de-serializers for your entities and aggregates. There shouldn't be an intentional 1-to-1 between them. In fact, most of the time you won't have the 1-to-1. In my code, I tend to scope repositories to the bounded context or to a subcontext.
Take a trivial example: A blogging application. I might have a repository that can persist a comment. Persisting the comment means saving the comment itself and updating User's comment count. The Save(Comment comment, Usr usr) method will make two calls to my persistence mechanism to update the individual Entities or Aggregates.
Repository, in the sense of domain driven design, is a life cycle management pattern. See chapter 6 of the "blue book".
It's purpose is to isolate from our application code the strategy we are using to store and retrieve aggregate roots. That's important, because the aggregate roots are the only parts of the domain code that our application code talks to directly.
From this, it follows that you don't need a repository for the client car relation unless it is the root of its own aggregate.
Figuring out whether this relation should be in its own aggregate or not is a matter of domain analysis -- you're going to have to dig into your specific domain to figure out the answer. For something like a car rental domain, I would guess that you'll want this relation, and the information associated with its life cycle, to be in a separate aggregate from the car or the customer. But I wouldn't feel confident in that guess until I had worked through a few edge cases with the domain experts.
Whether you treat an entity as aggregate root, thereby introduce a corresponding repository, depends on your domain or its ubiquitous language. One of the key indicators of aggregates is that they encapsulate important domain operations.
Hard to be precise without knowing your domain, however, in your example, Client seems to be a more natural candidate for an aggregate: a client may own new cars, get rid of a few, etc; the corresponding operations (i.e. adding cars or removing cars) fit naturally into client.
ClientCar (or ClientVisit), on the other hand, doesn't seem to have any purpose other than retrieving cars owned by a client. For this purpose, navigating the entity should suffice, no aggregate is necessary. Your Client repository may introduce a method for this purpose like the following:
public interface ClientRepository
{
Client findById(String clientId);
void store(Client client);
IList<Cars> carsOwnedBy(String clientId);
}
Then carsOwnedBy method implementation retrieves a Client and returns only the Cars associated with it.

DDD : create repository for an entity and its status

I have an entity in my domain which I need to track its status. And I have a handler for this need. This status is like InProgress, Completed or Deleted. And I use CosmosDb, SQL API for storing that data.
Inside CosmosDb, I have created a container for those created entities and another container for its status. Therefore, inside the code, I have two repositories for those two containers.
internal interface EntityRepository
{
Task AddAsync(Entity entity);
}
internal interface EntityStatusRepository
{
Task AddAsync(EntityStatus entityStatus);
}
And for each repository, I have created one service
public interface EnityService
{
Task AddAsync(Entity entity);
}
public interface EntityStatusService
{
Task AddStatusAsync(EntityStatus entityStatus)
}
Those services have been exposed as public interfaces for the handler and not repositories.
Now I really wonder
Based on DDD and having an entity and its status, should I create two separated repositories or they should be as one repository, as they are one context?
Do I need to expose the entity and its status through one service?
I wonder if anyone has a suggestion or even a better solution?
I'm not a DDD expert - just reading through Implementing DDD by Vernon but from my experience, you have an issue with bounded context. Your models Entity and EntityStatus are probably closely related. In that case you should create EntityStatusRepository only if you have a place where you need EntityStatuses by itself. If you need both of them just go with EntityRepository
It appears the EntityStatus should be a property on Entity, but let’s go through the logic to make sure. Note that these are not hard rules, just my rules of thumb when I’m going through these decisions. Extenuating circumstances my supersede these.
Should EntityStatus be an Aggregate Root? Would it make sense to
work with an EntityStatus by itself with no relationship to anything
else, or with only references to child objects? If not, then it is
not an Aggregate Root. That means it’s either a supporting entity or
a property.
If the parent entity always has exactly one current value of
EntityStatus, and no logic needs to be embedded inside the status,
then it is best to leave it as a property on the Entity.
If the EntityStatus needs logic built into it then it should probably
be a value object. For example, if status can only change from X to
Y in some circumstances but not others, or if some external process
must be launched when a status changes, it should be a value object
whose value is set by the Entity. Being a value object doesn't necessarily mean it's a separate entity, though.
Finally, I prefer to tie my repositories to Aggregate Roots even if there are value objects owned by the AR. An AR update should all be saved or nothing, and extending a DB single transaction across repositories is less than ideal. If you’re using the Unit of Work pattern, then an AR update should be a single unit. I’ve tried creating a separate repo per table where the AR repo uses the individual table repos, and it felt too granular with all the plumbing code. It was also easy to lose the business idea you’re trying to accomplish when dealing with all the pieces floating around. In the end, though, there’s no rule governing this so do what you think is right.

Business logic layer needs its own models or not

I'm doing 3 tier application using asp.net mvc and I want to do everything as recommended.
So I've done MvcSample.Bll for business logic, MvcSample.Data for data and MvcSample.Web for website.
In Data I've my edmx file (I'm using database first approach) and my repositories. And in Bll I'm doing services which will called in web.
So my question is that:
Should I write other models in Bll or use that ones which are generated in edmx file?
It heavily depends on the type of problem that your application is trying to solve.
From my experience, it is very rare that the business logic returns model objects directly from Entity Framework. Also, accepting these as arguments may not be the best idea.
Entity Framework model represents your relational database. Because of that, its definition contains many things that your business logic should not expose, for example navigation properties, computed properties etc. When accepting your model object as an argument, you may notice that many properties are not used by the particular business logic method. In many cases it confuses the developer and is the source of bugs.
All in all, if your application is a quick prototype, proof of concept or a simple CRUD software than it might be sufficient to use EF model classes. However, from practical point of view consider bespoke business logic model/dto classes.
From my point of view you need another model for your Bll.
That would encapsulate your Bllcompletely.
I think there is no right or wrong answer for your question.
In my experience, I used both.
Let's see at below example:
I have an User table
public class User
{
public int Id{get;set;}
public string First_Name{get;set;}
public string Last_Name{get;set;}
public int Age{get;set;}
public string Password{get;set;} //let's use this for demonstration
}
I have a Method call DisplayAll() in Bll. This method should list down all users in my database by Full Names (FirstName + LastName) and their Ages.
I should not return User class because it will expose the Password, but rather, I create a new Class UserDto
public class UserDto
{
public string FullName{get;set;}
public int Age{get;set;}
}
So here is my DisplayAll():
public List<UserDto> DisplayAll()
{
List<UserDto> result = ctx.User //my DbContext
.Select(x => new UserDto()
{
FullName = x.First_Name + " " +Last_Name,
Age = x.Age
}
return result;
}
So as you can see, my method DisplayAll() uses both User and UserDto
My approach will be
MvcSample.Data
-- Model Classes
-- EDMX attach to model
MvcSample.Bll
-- Model Inheriting MvcSample.Data.Model
-- Business Logic Class - Using MvcSample.Bll.Model
MvcSample.Web
-- Controller using MvcSample.Bll.Model
It depends on your view about software design and how you want to take advantage of it. by separating BLL model, you will have your freedom to put story specific validation and calculation. By using only DLL model, it is sometimes tough as it is going to take effect in DB.
You can use 3 tier architecture in asp.net in this way
MvcSample.BLL - business logic layer
MvcSample.DAL - Data access layer
MvcSample.Domain - Domain layer
MvcSample.web - website
All your repository classes are including in .BLL layer.That means your logics are stored here.
Usually .DAL is used for storing .edmx classes. .Domain is using for recreate database objects that are useful for server side.That means if you are passing a json object from client to server,Then that object should be create on the server side.So those classes can be implement in the .domain

How do I maintain referential transparency between related entities without relying on a common data context instance?

Thanks for looking.
Background
In my .NET applications I usually have a Business Logic Layer (BLL) containing my business methods and a Data Access Layer (DAL) which contains my Entitiy classes and any methods for dealing with atomic entities (i.e. CRUD methods for a single entity). This is a pretty typical design pattern.
Here is a pseudocode example of what I mean:
BLL
public static int CreateProduct(ProductModel product){
return DAL.SomeClass.CreateProduct(new DAL.Product{
Name = product.Name,
Price = product.Price
});
}
DAL
public int CreateProduct(Product p){
var db = new MyDataContext();
db.Products.AddObject(p);
db.SaveChanges();
return p.Id;
}
No problems with this simple example.
Ideally, all the business of instantiating a data context and using that data context lives in the DAL. But this becomes a problem if I attempt to deal with slightly more complex objects:
BLL
public static int CreateProduct(ProductModel product){
return DAL.SomeClass.CreateProduct(new DAL.Product{
Name = product.Name,
Price = product.Price,
ProductType = DAL.SomeClass.GetProductTypeById(product.ProductTypeId) //<--PROBLEM
});
}
Now, instead of saving the entity, I get the following error:
An entity object cannot be referenced by multiple instances of IEntityChangeTracker
Ok, so the answer to dealing with that is to pass a common data context to both calls:
BLL
public static int CreateProduct(ProductModel product){
using{var db = new DAL.MyDataContext()){
return DAL.SomeClass.CreateProduct(new DAL.Product{
Name = product.Name,
Price = product.Price,
ProductType = DAL.SomeClass.GetProductTypeById(product.ProductTypeId, db) //<--CONTEXT
}, db); //<--CONTEXT
}
}
Problem
This solves the immediate problem, but now my referential transparency is blown because I have to:
Instantiate the data context in the BLL
Pass the data context to the DAL from the BLL
Create overridden methods in the DAL that accept a data context as a parameter.
This may not be a problem for some but for me, since I write my code in a more functional style, it is a big problem. It's all the same database after all, so why the heck can't I deal with unique entities regardless of their data context instance?
Other Notes
I realize that some may be tempted to simply say to create a common data context for all calls. This won't fly as doing so is bad practice for a multitude of reasons and ultimately causes a connection pool overflow. See this great answer for more details.
Any constructive input is appreciated.
Personally, I track my unit of work and associate a data context to it via static methods. This works great if you aren't talking about operations with long lifetimes, such as my current project, an ASP.NET application, where every request is a (mostly) distinct unit and a request start and end coincide with the unit start/end. I store data context in the request CurrentContext, which, if you aren't familiar with it, is basically a dictionary managed by the system that allocates a request-specific storage accessible by static methods. The work's already done for me there, but you can find lots of examples of implementing your own unit of work pattern. One DbContext per web request... why?
Another equally workable answer for many is injection. Used for this purpose (injecting datacontext), it basically mimics the code you wrote at the end of your question, but shields you from the "non-functional" stuff you dislike.
Yes, you are only accessing one database, but if you look closely, you will see the database is not the constraint here. That is arising from the cache, which is designed to permit multiple, differing, concurrent copies of the data. If you don't wish to permit that, then you have a whole host of other solutions available.

Is Db access from my Services Layer a bad thing?

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.

Categories