I Am creating a web application and first use Entity Framework. I created Entity Data Model and now I am not sure, how to proceed now.
Premise: My database is really simple (Rating, WebPage, Visitor) and database tables corresponds to the business objects.
My suggestion is 3tier architecture but how to make it?
It is good idea create partial classes with the same name as Entity Framework objects (Rating, Visitor) and declare here new methods (GetAverageRating()...)? Or is better create some VisitorProvider, RatingProvider and place logic here?
It is better use EF objects in BLL and Presentation Layer or I should create my own BO objects on my BLL layer and transform EF object to BO?
I'm think, it is more practical use static methods on my DAL than instantiate classes on BLL. Do you agree?
Can you recommend me some best practices? I have many ideas how to create it, but I do not know what is the right.
3 layer architecture is quite popular but what it really means?
Presentation layer
Application layer
Database layer
If you ask what each layer means you can be pretty sure you will get several different answers. You can further divide each layer into sublayer and build layered hell like:
Client side presentation layer
Server side view layer
Controller layer
Service facade layer
Service layer
Domain objects layer
Repository + Factory layer
ORM layer
Stored procedure layer
Database view layer
Database table layer
WTF? That is just example that application can be easily over architected. It can go even worse if you insist that only neighbours can exchange data and if you decide to add special type of objects to be exchanged between layers instead of flowing sing set of objects through multiple layers.
Add layers which you need to make you more comfortable with developing the application and which will do reasonable separation of concerns and maintainability needed for the scale of your application. You can simply do the most simplest application which will be used just few weeks and must be developed as fast as possible. In such case you can do that within few days simply by using ASP.NET web forms and data source controls (or ASP.NET dynamic data). It can be badly extensible but in such situation it is exactly what you need to implement application quickly. Writing layers and doing all the stuff around maintainability and extensibility is reasonable if you need it. Another quick prototyping technique is ASP.NET MVC Scaffolding which can create quick multilayered skeleton of the application which can be further modified.
Both approaches are correct and it only depends on the approach you like. The first is called active record pattern but it is not used very often with entity framework. The second approach is more popular. You can either use EF directly in some middle class which you called Provider (common name is also Service). This class will do both data access logic and business logic. In more complex applications developers like to somehow wrap EF to separate class following repository pattern and call the repository either from service or directly from web app. code behind or controller (depending on amount of business logic). Try to do it without repository first. My personal opinion is that people should start to use repository only once they understand EF itself.
Again both approaches are correct. In a simple application it is fully acceptable to create EF model with POCO classes (EFv4.x) and use them in all layers. If you are using ASP.NET MVC you can find that you need special classes as view models to fully represent needs of your individual views. In a more complex application you can have separate objects exposed from a business layer - this is especially used if the business layer is exposed as a remote service (WCF).
It depends how you write these DAL methods - it is absolutely necessary to not share the EF context among requests! It also depends if you want to write some test or not. Layer defined by static methods is something which goes directly against testable architecture where you want unit test just single layer (unit testing with EF can be hard). It also depends if you want to use dependency injection which is based on instances.
Related
In typical DDD architecture we have 3 layers:
Domain - no references
Application - it has reference to Domain layer
Infrastructure - it has reference to Domain layer
(+ Web / UI project)
Domain models live of course in Domain layer. But in which layer should live read models (projections) for read database, for example MongoDb?
Short answer, both Application Services (Application layer) and Repositories (Infrastructure layer) know about the READ models. The domain layer remains transparent to underlying persistence and loading mechanisms.
Long answer, the exact usage mechanism depends on how you use the read models. You could either be using them to construct objects used in your domain layer or more typically, only as responses to API queries.
First case: Use Read Models as objects in the domain layer
The Application service loads the READ model from the repository into the domain entity. It is the repository's responsibility to populate the READ model correctly into the domain entity. The repository is also responsible for transforming the domain entity into the WRITE model to persist in the primary database.
By the time you get to the Domain model, objects are already loaded into memory with the help of repositories. So the domain layer does not even know about the READ model and a WRITE model; it only deals with the domain entity.
Second case: Use Read Models for storing pre-built responses to API queries
This scenario is a more typical use of the READ models. Usually, there are more than one read models for the same Entity/Aggregate because they are custom-built for specific API requests.
In this case, we don't even touch the domain layer. The Application Service accepts the request, uses the READ model repository to load the object, and return a response to the application server.
There's no written law that dictates in which project a read model should live. In my personal opinion, I think having a separate read model project has its benefits. With command query responsibility segregation things tend to get pretty confusing if the command-part of the application can access the query-part of the application. I think the two should be clearly separated.
I've spent some time working on an example project that demonstrates how to set up your DDD/ports-and-adapters/CQRS application. I've dropped the code on GitHub: https://github.com/appie2go/steal-this-code
I've also spent some time to explain the choices I've made in detail in the following articles:
https://medium.com/#abstarreveld/implementing-dddomain-models-ports-adapters-and-cqrs-with-c-2b81403f09f7 and,
https://medium.com/#abstarreveld/dddomain-models-ports-adapters-and-cqrs-reference-architecture-c-504817df65ec
Hope it helps!
Cheers
To be honest, it doesn't really matter. There's no default structure for neither DDD-oriented implementation or event sourcing-oriented implementation.
You can perfectly have a single project if the system is small. If you want to keep your domain clean of external references - you can keep it in a separate project and take care of having zero references except for something you need to support the domain model basis, like entity base class and so on.
Read models and projections are completely orthogonal to the domain model and you usually need them for the query API or query services. You will benefit from keeping read models (documents in case of MongoDB) and projections in one place. You can either reference this project from your API project or keep the query API, query services, query models, read models and projections together.
Again, I would argue that such a thing as a "typical DDD architecture" doesn't exist, because DDD is not architecture to start with. Splitting projects is more a developer convenience and discipline concern and splitting the system is the architectural concern, which is not DDD-specific.
One thing that also comes to my mind is that if you really think DDD, you might first want to find out what is your context map, how many domain models you really need and maybe there you can find some ideas about separation, not based on technical concerns really.
In a 1 tier application i.e Mvc, you get a folder called models and you build and store your classes in there, I'm aware when it comes to a three tier application from what I have read it seems correct to store the models inside the business layer (2nd tier), and from the UI (first tier) I would add a project reference to the 2nd tier which will allow me to use the models and make calls to methods.
From the second tiers perspective it would call the data layer (third tier) and perform crud operations against the database, but the data layer would require the models from the business layer so when I try to add a project reference from data layer to business layer i get the error
A Reference to "Business Layer" could not be added, adding this project as a reference would cause a circular dependency
Which I understand as a reference has already been made via business layer to data layer
How would I get around this? do I create additional models in the data layer and populate them with results from the database and pass that back to the business layer which then passes it back up to the UI? I'm slightly confused on this.
** Update **
From what I have read for the data layer to reference models inside the Business layer I would need to do model mapping, My model mapping will be quite large so I'm thinking of including a 4th tier which will be a shared library and that will consist of all the models that way the data layer and the business layer can access the models as and when is required.
A little off topic but ...
Depending on the size of your application, there may be no reason to introduce unnecessary complexities to try and follow pattern you may not necessarily understand. Doing so, will cause you extra headache.
That being said, if your project is of a large size and requires some good organizing, I would strongly suggest more research and maybe a few sample project in where you try out the architecture you came up with. No way you'll get it right the first time.
I would personally suggest looking into "onion architecture" instead of "n-tier", and of course you'll find many different views on it. You'll have to make your own decisions.
Here's a generic set-up I would start off with.
Core. It knows about no other project. This is where your classes with your "business" go. Such as Customer, Product, Order, etc.
Data. It knows about Core. It is responsible for taking in a Core object and storing it somewhere. That is all.
Service. It knows about Core AND Data. It's job is to expose methods such as "Create Customer", it will be responsible for creating a customer and storing it.
Web / Api / Mvc. This will know about Service. It's job is to expose your service to the user. (UI and such). (It may also know about Core / Data ... but that's a larger discussion.)
You're on the right track but I find it easier to think of the model layer as the data (third tier), the controller (business layer, second tier) manages the flow of the data between the ui (first tier) and the data layer.
If you modify your architecture this way, you should get rid of the circular references.
This also allows you to map your data layer objects to the appropriate less/more complex structures of the middle tier in a way which simplifies the interface shown to the UI and encapsulates the business logic there too.
In a layered application, is it good practice to have you entities defined in a shared layer? I figure that I will be using them across all layers. Or do they belong in the business layer?
MSDN's layered application guideline puts the business entities in the business layer
The Layered Architecture Sample for .NET puts the entities in the shared layer
Can it be like this?
Presentation
Business
Data
Shared
Entities
Or must it be like this
Presentation
Business
Entities
Data
Shared
What to do and why?
I usually organize projects in following structure:
Presentation (MVC application)
try to keep your controllers small as possible. Do not put any business logic into controllers. Relay on service interfaces instead concrete implementations. Use dependency injection.
Business layer
service classes belong here and they should contain all business logic
i group related services into folders by feature. Each service queries the DB with entity framework and maps the results into Model (a.k.a. View Models, Presentation Objects) objects. So the service layer does not return DB entities but return POCO classes.
shared folder contains services which are shared across multiple services (they are more like infrastructure code but i prefer to keep them inside the business/service project)
DAL data access layer
I prefer to use only entity framework without any other abstraction upon it. Some people use Repositories or implementing own unit of work pattern, but i do not recommend to do this. Entity framework is already implementing unit of work and encapsulating database selects with linq so there is no need for more abstraction.
this layer contains only Code First classes (entity framework entities)
I would say it depends if these entities contain business logic or not.
From the Layered Application Guidelines :
Business entities also validate the data contained within the entity
and encapsulate business logic to ensure consistency and to implement
business rules and behavior.
In contrast, the Layered Architecture Solution Guidance seems to rely on code generation to create Entities, they are mere data containers with little to no logic in them.
Rich domain entities tend to not be in a Shared module, since it would mean carrying around a ton of behavior that you don't want everyone to have (imagine being able to manipulate business logic directly on the client side...) Anemic ones on the contrary are lightweight and may be happily and conveniently distributed everywhere.
My approach is a little bit different. In data layer I store all my entities and in shared layer I have DTO object (Domain Transfer Objects) which are exact copy of entities but without Entity Framework control. To map each other, I'm using mapper (AutoMapper) which is fluent and easy to use.
I can't understand why Entity Framework doesn't support interfaces, using only instances.
I have been a little confused with trying to determine where to put the business rules for my application.
I am developing an web application using asp.net conventional web forms (not mvc) and on top of that I have a class library where I have the repository pattern for writing to database. I have a "Business Layer" in the repository pattern and also, I am writing stored procedures to affect the tables.
Where should I put for example, Mandatory field validation rules ?
Other example would be, converting foreign currency to USD (i have an exchange rate table, currently I do it in sprocs).
Would you recommend staying away from the sprocs for rules and build everything in my repository business layer ? or In what cases do you recommend building rules and validations within the sprocs ?
This answer is appropriate if you develop a small application that does not use multiple data sources or does not have an extensively unit-tested business layer and if you do not plan to add a service layer (such as for caching). See the opposition in the comments.
If I may, I can suggest to:
Remove repository pattern completely. Do you really need to support multiple databases?
Keep business logic in a business layer, not database. The benefits are in the locality of the rules. All your domain is expressed as a set of conditions, rules, strategies etc. And it is all located in one place. Should you choose to store them in a database you would create yourself additional headache when maintaining the code.
It is easy to unit test code that is in the business layer. I am not sure if it is possible to unit test SP.
SP and Repository pattern don't go well together.
Currency rate change every fraction of a second, for this you should use a reliable web service that you can call and get a precise value.
Summary:
Stay away from SP
Stay away from repository pattern
Use ORM directly instead of repository pattern abstraction
Don't mix persistence and business rules
Separate your business rules in a separate (reusable) assembly
Your repository is NOT supposed to have a business layer. It's sole purpose should be to act as an abstraction of your database. Inside it you manage how you store/retrieve your application data.
Use SP for database operations that are not subject to frequent change. NEVER put your business logic inside SP. Business logic have tendency to change over time.
You can create a domain-layer where your business objects reside. Your business object should encapsulate their own validation logic.
Other than your business/domain objects you may have utility classes (e.g. CurrencyManager or CurrencyHelper) that actually use your business objects to verify business logic against data.
Finally try to keep your domain free from any sort of presentation/view layer reference. Don't apply business validation rules at view layer or display validation logic at domain layer.
-hope that'll shed some light.
I have been working on coming up with the best wy to put the classes for the best OOP. Sometimes I wonder if I am trying to over kill the thought process.
I am thinking now to have as an examples the Categories Object
Files
Cateogories.cs - Object File
CateogoriesDAL.cs - Data Access Layer
CateogoriesBLL.cs - Business Logic Layer
CateogoriesWS.cs - Web Service
When you call form any application local or external you would call the web service and it would get what you need.
Examples:
You would create a Categories Object so you could pass it to the Web Service Layer when you wanted to Save (Insert or Update) a Category. All of the business rules would be in the Business Logic Layer.
How do you implement the OOP?
You might want to look into using an Object/Relational-Mapper (ORM) such as Entity Framework or NHibernate to simplify things. You could then use a simple domain driven approach with Repositories, Services etc.
EDIT: The repositories are responsible for the actual interaction with the data layer; Get/Save entities. Then you could use Domain Services for actual "business logic".