3 layer design question, binding data to form - c#

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.

Related

Pass EF context on a project with multiple layers

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.

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.

In which layer entities class must be defined?

When creating a Business Model in which layer (GUI, BLL, DAL) entities class must be defined?
Your entities are a part of your Business Logic. In your entities you define your business rules.
They should be ignorant of the type of Data Access you use. This can be done by using the Repository pattern. In your BLL you define your Repository interfaces which act on your entities. In a separate infrastructure project, you will define an implementation for the Repositories.
If you pass your entities to your GUI is a matter of choice. Sometimes it can be beneficial to use special crafted classes for passing data to your view but in a small project you could opt for passing your entities directly to your GUI.
You can define it in two places
Either create a new Layer Model/Entities (preferred)
or
Define them in Data Access Layer
I would say: in their own layer. The GUI, the business layer and the data access layer all use the entities. But the GUI doesn't depend on the data access layer, and the data access layer doesn't depend on the service layer. So entities must be in their own domain layer.
It depends from the way you want to use your entity. If it's simple POCO object, that used as DTO from db to you application, so i think that best place will be DAL. If you want to use your entity like part of business logic and it has some functional - so BLL will be the best place. But I don't think that there are some cases when it should be used and defined in GUI
I think that it's a good practice to have an ViewModel for any GUI purposes. Because when you use EF than it means that you interact with SQL somehow (in most cases). So you data is normalized. For there other hand many times you need denormalized data for GUI. That why i prefer to use ViewModel for GUI.

Three tier architecture question

I have an ASP.NET app with a three layer architecture:
Presentation layer: ASP.NET
Bussiness Layer: C# library.
Data Access Layer: C# library with
ADO.Net Entity Framework objects.
Some methods on Bussiness layer would return ADO.NET entity objects but, data access layer is not visible at Presentation layer I can't do that.
My question is: On a design view, Is it correct to expose Entity Objects in the Presentation Layer? I think I only have to link Data Layer library with ASP.NET app.
Thank you!
It's absolutely desirable to have your entity objects available for use and consumption in your presentation tier. That's what all the work is for.
Binding collection of objects to a grid/listview/dropdown
Splashing a single object (i.e. customer) onto a form for read/update/delete
This makes your life easier by far. Otherwise you'd have to pass string after int after double after string between your presentation and business layers.
These may be Entity objects or even your own POCO objects that were hydrated from the Entity objects.
I would even go so far as to say that your Entites should be in their own assembly separate from the DAL.
I suggest that you look into the concepts of View objects...or Data Transfer Objects (DTO). You might consider using a tool like AutoMapper or similar which will create a view specific domain object out of your entities. In general you may have screens that need an entity present to perform its work. But more often than not you will need to pass several different entities. In this case you are better off creating one DTO that contains all of these entities. By doing this you are adding a layer of separation between your presentation layer and your business layer. Often times your entities have more power than you might want to expose to your presentation layer. And...vice versa. Frequently you may need to get some UI messages out to the presentation layer based on some validation flagged in your business layer. Rather than make your ui more complex than it needs to be (by passing in your full entities) you can only pass in what the UI needs in the form of the DTO. Also, there is never a need for your business objects to care about anything specific to the presentation layer. I suggest that you not databind directly to anything as far back as the data access layer. Technically your presentation layer should know as little as possible about your business layer. In the case of MVP or MVC this is very easy to achieve by disconnecting the front end and the back end by way of this additional separation!
I think no, it is not, the best way to do that is to separate data classes from behavior, and reference only data classes in presentation level.The good approach I think to use WCF see this link
See Supervising Controller and Passive View
If you pass the Entity, you are essentially Supervising controller. Otherwise you are Passive View.
Supervising controller is less work, but less testable. Supervising Controller also says databinding is OK.
Passive view is testable but a LOT more work. No databinding. Lots of properties.
Typically I stick with Supervising Controller. You typically don't need that level of testability and it isn't worth the extra trouble.

n-Tier Architecture Feedback Needed

I started my website, like stackoverflow, with a little technical debt that I'm trying to pay off. Being a contract developer, I've been in many places and see many different methods of achieving this result, but the way I'm going is..
Presentation (web)
Business Layer (old fashioned entity classes and BL layer)
Data Layer (DA classes to SQL Server via Stored Proc)
My question primarily concerns the Business Layer. Right now I have an Entity namespace and a BusinessLogic namespace.
The BL has a reference to the DA and the Entity.
The Entity has a reference to the DA
(The DA is "unaware" of the BL or Entity)
I really want all my churning of turning Data into Entities to occur within the BL -- thus the Business Logic. However, I want the Entity to be able to access the BL if need be -- and thus remove the Entity's reference to the DL.
So...
Is is "wrong" to have the BL and Entity objects within the same namespace so they can work together?
Essentially, I'm trying have an entity object like Employee (classic example, eh?) and have the Employee have a
public Hashtable[] SubordinateEmployees
property that returns a Hashtable of other Employee objects that report to this employee. But I don't want to load it until it's needed. So for most employees the property would never get accessed, but when it does, it self-loads with a call to the BL, which calls the DA.
Does the question make sense?
If so, does my solution?
Thanks so much in advance!
The usual way to deal with the kind of situation your example represents is with facades. Instead of trying to get the subordinate employees from the Employee object, you use a call to the business logic to get it.
hashtable = BL.GetSubordinateEmployees(supervisor);
That way you have a single point of access to the subordinates, and there is only one thing (the BL) accessing the data layer and creating Entities.
Let me see if I can show you a better way to think about this
you have your data access (sql server, mysql, flat xml files, etc.) all of this should be abstracted away nothing else in your application should care or know how you are getting your data, only that it dose, if anything else knows how you are getting your data you have a layer violation. if the DAL dose anything other then get data you have a layer violation. Next you implement a data access interface something like IDAL that your business layer uses, this is very important for making your code testable by forcing you to separate your layers.
Your data entities can be placed in the DAL name space or give them there own, Giving them there own forces separation. Data entities are dumb objects and should contain very little to no logic and are only aware of themselves and the data they have, THEY DO NOT CONTAIN BUSINESS LOGIC!, DATA ACCESS LOCIC, OR UI LOGIC. if they do you have a layer violation. The only function of a data entity is to hold data and be passed from one layer to the next.
Biz layer implements a data access interface like the IDAL we talked about before you can instantiate this with a factory, an IOC container, or all else failing a concrete type, but add a setter property so this can be changed for testing. The Biz Layer Only handles Business logic, it doesn't know or care where the data came from or where it's going, it only cares about manipulating the data to comply with business rules, this would include date validation, filtering (part of this is telling the DAL what data it needs, let the DAL figure out how to get it). Basically the BIZ handles all logic that isn't UI related or Data retrieval related. Just like the DAL the Biz should implement an Interface for the same reason.
The UI layer Accesses the Biz layer the same way the Biz layer accesses the DAL for the same reason. All the UI layer cares about is displaying data and getting data from the user. The IU Layer should not know anything about the business rules, with the possible exception of data validation required to populate the Data Entities.
The advantage of this architecture is it forces separation of concern making it easier to test, more flexible, and easier to maintain. Today you are building a web site but tomorrow you want to allow others to integrate vi a web service, all you have to do is create a web service that implements the IBIZ interface and your done, when you have to fix a bug in the BIZ layer, it's already fixed in both your website and web service.
Taking this to the next level, lets say you are doing a lot of heavy number crunching and you need more powerful servers to handle this so all you have to do is implement an IDal and IBIZ interface that are really wrappers to WCF that handles the communication between your servers, now your application is distributed between multiple server and you didn't have to change your code to do it.

Categories

Resources