Introduction
We require to build a n-tier application, as we would like to share our BL over multiple platforms and only write our DAL once. I've already done some research on this subject.
As can be read here in Davide Piras's post: MVC3 and Entity Framework each VS solution must at least have 4 layers. So far so good.
He also states that the DAL project is the only project which is allowed to even know that EF is being used.
Question 1:
I'm assuming, that the interfaces of the 'Interfaces' project are a 1 on 1 representation of my EF entities, am i correct on this? Also, these interfaces should be used as types between the different layers?
Question 2:
MSDN advices that the lifetime of a DbContext should be one context per request for WebApps, and one context per form in a WPF or WinForms project. So, how can i achieve this without adding 'System.Data.Entity' to my GUI layer?
Thnx in advance!
First of all DO NOT!!! share your DAL over multiple platform. Share your BL which uses DAL. As long as your BL represent solutions to your application requirements you do not need to expose your DAL and, please don't. Also exposing DAL has the disadvantage of exposing more vulnerabiilties to hackers and direct acces to DAL provides a btpass mechanism to your Business Logic, Controls and Validations in your BL.
Answer 1: Possibly but not need to. Thinking with SOA in mind I suggest to use DTOs. Either they are entities or more complex, composite classes of several and/or partial entities. If you use entities this gives you more flexibility to provide information via BL (you can send several portions of data at once by one method call) and hides youe entity (also DB structure) from third party users providing a better sense of security.
Answer 2: Again, thinking with SOA in mind, do not construct your BL/Service methods according to your User Interface. BL (as the name implies) provides data according to "how the work is done" not "how the work is done by the user on the screen". And if you try to manage your data from GUI you will also start to violate N-tier architecture. DO NOT!!! use any data spesific class and/or methods outside of DAL. This will be the true use of layering.
Regards.
You need to use Unit of Work
and Repository
patterns with a Dependency Injection framework like StructureMap or Unity.
Basically, what you need to do is to create interfaces:
public interface IUnitOfWork
{
void SaveChanges();
}
public interface IRepository<TItem>
{
TItem GetByKey<TKey>();
IQueryable<TItem> Query();
}
Now, in your DbContext
class implement the interfaces above and somewhere in your Business Layer register the implementation of the interfaces:
public void RegisterDependencies(Container container)
{
// Container is a Structure Map container.
container.ForRequestedType<IUnitOfWork>()
.CacheBy(InstanceScope.HttpContext)
.TheDefaultConcreteType<DbContext>();
}
See StructureMap Scoping Docs on how to configure the scope of an instance.
Now, with all that code in place, each of your Business Layer
class that needs to perform some data operations would look like this:
public class SomeService
{
public SomeService(IRepository<SomeItem> repository, IUnitOfWork unitOfWork)
{
this.repository = repository;
this.unitOfWork = unitOfWork;
}
public void MarkItemCompleted(int itemId)
{
var item = repository.GetByKey(itemId);
if(item != null)
{
item.Completed = true;
unitOfWork.SaveChanges();
}
}
}
Now, hide the creation of services behind a factory:
public class ServiceFactory
{
private readonly Container container;// = initialize the container
public TService CreateService<TService>()
{
return container.GetInstance<TService>();
}
}
And in your GUI layer call only methods of service classes created through ServiceFactory
; if your GUI is an ASP.NET MVC project you don't need to create the ServiceFactory
class - you can derive from DefaultControllerFactory
and override GetControllerInstance
method. See the answer here for an example.
来源:https://stackoverflow.com/questions/28338064/ef-n-tier-architecture