Pass EF context on a project with multiple layers - c#

I have an application that is separated into 4 layers to keep code organized and be able to reuse it.
My layers are:
presentation layer: an mvc4 project
business layer: a c# library project whit the Business logic
Data layer: a c# library that contains all the linq to the db
model layer: a c# library that contains a edmx ef5 for my database
So the idea is that for each controller or our mvc project we have 1 business class and 1 data class. and if some functionality needs to make use of code on other class, they do at business logic layer (different business logic classes can create new instances of other business logic classes.)
The problem I was having is that I was creating too many DbContext and I was getting some errors and problems because of it. Like loosing the lazy loading on my BL layers or not been able to assign objects like list to other objects when they came from different DbContext.
For example, if I have a medic controller/logic/data and I use a patient logic/data to get a list of patient for today, I get an error when I try to do medic.patients = patienstList;
So what I need to do is use one DbContext per web request, so the DbContext will be created on the controller and injected to the logic layer and those will inject to other logic class or to the data classes?
How can I do it?

There are number of ways of doing IOC in MVC.
Example would Unity.. where you can register an instance of DBContext.
Of course if the lifetime of you IOC container every extends beyond web requests. your are in for nasty time.
Even if you think it is 1 Context per request that you need. Be very careful if you use ASP pipeline events and access DbContext, you may actually need 1 context per Thread. But if you are happy to say you access starts at MVC Controller level. Then you are looking for a way to handle inversion of control only.
Unity from microsoft
dependency injection docu
https://unity.codeplex.com/documentation

IMHO the Business Object should not have to use another Business Object because that violates the Single Responsibility Principle.
The Data Layer object should be able to do everything the Business Object needs it to.
So you should write methods in the Business Layer Object and Data Layer Object method GetPatientsForMedic.
You may say "but the Hospitals Business Object can get me a list of Hospitals really easily". That is not it's job, because you said it's job is to service the Hospitals controller.
HOWEVER the problem only happens when you pass a Hospital object from the HospitalsBO to the MedicBO. So don't.
On the Hospitals controller, write a method GetListOfHospitalIDsAndNames. Then, if you need a dropdown of hospitals, call that, and use the IDs and text names.
You can indeed share a DbContext between two Business Objects by sharing a Unit of Work. But you probably shouldn't.
However i'm no expert... i avoided these problems by having one GINORMOUS business object with everything in it. That is also a BAD THING.

Related

Three Tier Application

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.

How do you implement a business logic layer when using entity framework as data access layer?

Say i have 3 layers
layer 1: WPF Project (contains: xaml, viewmodels, mvvm framework)
layer 2: business logic layer (contains: plain c# classes)
layer 3: entity framework (contains: repository/data access classes)
when you dont want to expose your DAL(layer 3) to View(layer 1)
how do you implement the business logic layer well?
im having a hard time putting values back and forth the BLL objects and DAL entities.
can you please help?
Entity Framework doesn't work really well in a "disconnected" model. Unless something has changed, I've never been able to get it to work great easily.
You could use AutoMapper in Layer 2 to create ViewModels to present to Layer 1, but then you'd still have to send the changes back to Layer 3, which could be a pain.
If you're only developing a small app that will not change in the foreseeable, then just do whatever is quickest now. If you want a long-term maintainable app, then let me put forth the following.
The problem with this vertical layer approach is that whenever you need something in the view, you will have to add it to both the Business Layer (even if the business layer doesn't care about it), and the Data Layer. This requires your business layer to look like 1) UI views of the data 2) business views of the data and 3) the database representation of the data. That and/or you need a lot of mapping in-between layers. All of which dilutes business layer's actual purpose of representing business logic. What tends to happen then is that all the business logic gets migrated into transaction methods (that could just as well be static methods) to just change states on data objects. There's nothing at all wrong with that if your problem domain is nothing but CRUD with no complex logic. With complex logic, such business methods can get pretty tricky or even have undefined outcomes (because complex interdependencies on "fields" can be contradictory and hard to resolve).
Assuming you have complex logic, user views of data and business representations of data are often very different, and so UI views end up with specialized models of the data. If I were you, I just embrace this and use a simple version of the CQRS principle. That is, have the data for your UI views come from a different place than where your business operations are executed. In your case, I might have an EF Model in your DAL that only services your UI views, and gives them exactly what they need (whether by database views, stored procedures, or pre-compiled report tables). Then create a separate EF model that services only the needs for your Business entities. Then when you are ready to perform an actual business action, the UI's viewmodel action method can load the business object from the business EF model (or better yet, call an object factory from the business layer which does this) and run an appropriate action on the business object. Note that I'm also making the assumption here that your database is highly relational (mostly 2nd and 3rd normal form) and you are set on using EF.
I would not try to make your View Models into business logic. This makes your business logic not easily reusable on other platforms or applications (like web). MVVM should only service the UI. In my mind, the V (view) represents what the user sees and operates. The M (model) represents what the user chose on that view. And the VM (view model) translates between the two. Your program should then take the user's validated choices (UI model) and extract the needed data out of it to perform an appropriate business operation.
Instead of exposing all of your DAL to View Layer, just exchange your domain objects (EF objects) between all layers. The structure may be similar to the following:
Presentation Layer-------- ^
BLL --------------------------- | Data objects
DAL (Repositories etc.)--- |
So, all of your layers will be disconnected; but they will share the same domain objects. In real world, you can implement a similar structure by creating a seperate dll for Entity Framework entities which is shared by all layers. Note that ObjectContext shall be only visible to DAL (by default, entities and object context are generated in the same dll, you need to seperate this into two dlls).
In addition to the answer by Daryal, you can define your business-objects in your BL to be POCO's, and use EF in your DAL layer to read them from or persist them to the database.
If you define an repository-like interface in your BL (or unit-of-work, whatever naming you give it), and implement the interface in your DAL, then all you need is a little DI to get an instance of the repository-class without having to reference the DAL all the time. It works like a charm for me.
See here and here for more information.
Your ViewModels are your application in MVVM, so they should be handling things like data access through your Repository classes, or business logic (either directly, or indirectly using your validation classes).
If you don't want to directly reference the classes, use an Interface but be aware that you'll need to have some way of passing your inherited class to your ViewModel. I once did a project where we had a library of shared interfaces, such IRepository interfaces, and everything was imported/exported using MEF so the layers didn't reference each other directly.
The final (simplified) layout was:
Models -> Contained plain data objects that could do simple validation on their own data (length, min/max values, etc) but that didn't do any advanced validation or business logic. Did not reference any other library.
Common -> Contained interfaces, utilities, and other commonly shared classes. Referenced the Model library only.
DAL -> Contained Data Access and Repositories based on repository interfaces found in Common library. Referenced Common library for interface definitions and utilities, and Model library because it contained the data models used or returned in data access calls
ViewModels -> Contained application and business logic. Referenced Common for its utilities and interfaces, and Models for the data models
Client -> Contained Views. Referenced Models and ViewModels so it could write DataTemplates for both object types
Entity framework is suppouse to be used as "Logic Layer" by itself.
Your idea may have some sense, to use combine technologies.
Howevere, I think some of those Micros. libraries, where designed to be used separately, unless, otherwise explicitly combined & mentioned in their websites.
Good Luck.
I second daryal and I have implemented this in some projects. It is absolutely OK to use POCO as business objects.
Another approach instead of creating 2 projects (one for DB Context and one for Entities) is to use one DAL/DATA project only and reference it in BLL. Then inherit the POCO class in BLL and use that class in UI layer. Below is the basic sample code:
// assume this is EF generated POCO
namespace Owner.Project.Data{
public partial class Product
{
public int ProductId { get; set; }
public string ProductName { get; set; }
}
}
// this is manually created class in BLL
using Owner.Project.Data;
namespace Owner.Product.Business{
public class StoreProduct : Product {
public bool Add (string productName){
// TODO - add product using EF as you normally do
}
}
}
Now you can reference the BLL in your UI project and use StoreProduct class there. To achieve loosely coupled pattern, Of course you could also inherit the StoreProduct class from an IStoreProduct interface and make use of it in UI or web service but that is another topic.

Entity Data Framework and Web app architecture

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.

3 layer design question, binding data to form

I want to bind controls on form to a data from database, the binding happens in codebehind.
I want to use 3 layer pattern, DAL layer that will use Entity Framework, BLL that will use DAL to retrieve the data, and my form to display it.
Let's say there is an Entity object called Product with 3 properties: Name, Count, Price
I want to bind them to 3 text boxes on the from.
from code behind I call BLL's method that will call DAL method to retrieve the needed entity object...
Here is the problem, in order to bind data on the form, form must "know" about this entityObject that returned by BLL.
So I could do this:
DataAccessLayer.Product product = BusinessLogicLayer.GetProduct(someid);
textbox1.text=product.name;
textbox2.text=product.price;
....
But this breaks the 3-layer pattern!!
How to be? Create a new object just to hold this data?
I typically separate my business objects and interfaces that deal with these objects like IRepository into a Domain project. Then my DAL can reference this project and so can my web project.
UPDATE
Project structure:
Domain - contains entities,
interfaces
DAL - contains data access logic,
implements interfaces form Domain
BLL - contains business logic, uses
DAL and Domain, potentially
implements some interfaces from
Domain as well
Web - contains pages, uses BLL and entities/interfaces from Domain
Work with interfaces. Then your form knows about some IProduct, but does not need to know about the specific implementation. You could use NInject for example, to do the dependency injection.
The most common way and also a best practice is to use a client side repository. You can abstract your entities into domain objects. You can use a mapper like AutoMapper to map the data transfer objects (DTO's) which are returned by the service layer and the domain entities which are used by the application layer. By abstracting this behind a repository your application layer need not know about the servie layern and the two can vary independently.

Services and Repositories in DDD (C#)

How do Services and Repositories relate to each other in DDD? I mean, I've been reading up on DDD for the past 2 days and everywhere I go, there's always a Service layer and there's always a Repository layer. How do these differentiate or compliment each other?
From what I've read, isn't the Repository the layer responsible for delegating interactions between the application and the data?
So, what's the need for the Service layer if it has to implement the Repository to interact with the data anyway even though the Repository probably already implements the methods needed to do so?
I'd appreciate some enlightenment on the subject.
P.S. Don't know if this will help any, but I'm working with an ASP.NET MVC 2 application in which I'm trying to implement the Repository pattern. I just finished implementing the Dependency Injection pattern (for the first time ever)...
UPDATE
Okay, with so many answers, I think I understand what the difference is. So, to review (correct me if I'm wrong):
A Repository layer interacts only with a single object out of the database or the ORM, IEmployeeRepository -> Employee.
A Service layer encapsulates more complex functionality on objects returned from Repositories, either one or multiple.
So, then I have a sub question. Is it considered bad practice to create abstract objects to be sent to my views? For example an AEmployee (A for abstract because to me I means interface) which contains properties from Employee and X or X?
Actually, one more subquestion. If a Service layer can be considered "tuned" for an application does it need to be implemented with an interface?
The Service will use a Repository to retrieve an Entity and then call methods on it (the Entity) to perform the Command/task.
True, a repository works with data (ie. SQL, Webservice etc.) but that's the only job. CRUD operations, nothing more. There is no place for stored procedure based busines logic.
The service (or business logic layer) provides the functionality. How to fullfill a business request (ie. calculate salary), what you have to do.
Oh, and this is a really nice DDD book:
http://www.infoq.com/minibooks/domain-driven-design-quickly
As a concrete example a Shopping Cart application might have the following services:
ShoppingCartService - manages a cart of items with add/remove/update support etc.
OrderService - take a cart, converts it to an order and handles the payment process etc.
each of these services needs to talk a "data source" for CRUD operations. This is where the Repository pattern comes in handy as it abstracts the loading and saving of data to and from the data source be it a database, web service or even in-memory cache.
When you want to create a quick prototype of your application without having to deal with database setup, schema, stored procedures, permissions, etc. you can create a cache or fake repository in a matter of minutes.
For the example above your prototype might start off with the following:
FakeCustomerRepository
FakeAddressRepository
FakeCartRepository
FakeCartLineItemRepository
FakeOrderRepository
FakeOrderLineItemRepository
once your prototype is ready to evolve to the next level you can implement these against a real database:
SQLCustomerRepository
SQLAddressRepository
SQLCartRepository
SQLCartLineItemRepository
SQLOrderRepository
SQLOrderLineItemRepository
From what I can remember, the repository is the final class before the data. The service class can act on data retrieved from the repository. The repository is really just meant to get data to somebody else to do the work. The service layer can provide things such as business logic that all data must pass through. It could also provide for a translation between the application logic and the data layer. But again, this is just what I can remember.
There's no golden standard that defines a service or a repository. In my applications a repository is (as you say) an interface into a database. A service has full access to a repository - but the service exposes a subset of functionality to its consumers.
Think of the repository as more low level. The repository has to expose many ways of accessing the underlying database. A service might combine calls to a repository with other code that only makes sense at a code level (i.e. not in the database), such as access to other state in the application, or validation/business logic that can't easily be applied in a database.

Categories

Resources