Here is what I would do. To decouple the DAL from the UI, you will need a "middle tier". Consider the following diagram.

The middle tier is widely know as the service layer or the application layer.
Everytime the Person
data passes from one layer to another, it is "mapped" to its equivalent class for that specific layer.
The following snippets makes up the very basic example of a service layer. I did not include the other details such as AutoMappers and other general practices.
The PersonDto
, defined in the middle tier, represents the Person
entity.
public class PersonDto
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
The PersonService
class. It encapsulates the data access and business logic, and returns only the PersonDto
(instead of the entities). It is how the UI communicates with the domain.
public class PersonService
{
public PersonDto GetPersonById(int id)
{
Person person = dbContext.Persons.Find(id);
// Mapping in action.
var personDto = new PersonDto()
{
FirstName = person.FirstName,
LastName = person.LastName,
};
return personDto;
}
}
This PersonService
is what the UI code sees, it does not know about the data access or the business logic. It only knows about the services.
The services should encapsulate your business logic, decoupling the UI from the BLL and DAL.