Lets say I have the following entities that map to database tables (every matching property name can be considered a PK/FK relationship):
public class Person
{
public int PersonID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class Employee
{
public int EmployeeID { get; set; }
public int PersonID { get; set; }
public int Salary { get; set; }
}
public class Executive
{
public int ExecutiveID { get; set; }
public int EmployeeID { get; set; }
public string OfficeNumber { g开发者_C百科et; set; }
}
public class Contact
{
public int ContactID { get; set; }
public int PersonID { get; set; }
public string PhoneNumber { get; set; }
}
My architecture is as follows: Controller calls Service layer which calls Repository layer.
I have a View called AddExecutive
that collects the following information: FirstName, LastName, PhoneNumber, Salary
, and OfficeNumber
.
What is the best way to commit this data given my architecture? I am thinking I that I would post up a ViewModel that contains all the information I collected and pass it off to a Service method AddExecutive(AddExecutiveViewModel addExecutiveViewModel)
, then within the Service method I would create new instances of Person, Employee, Executive,
and Contact
and attach them to each other (Person
object) and pass ALL the data off to a Repository method AddExecutive(Person person)
. The Repository method would then simply commit the data. Does that sound right? What would be a better solution?
So long as you maintain separation of concerns you good. Controller: Binds data to service / model Service: Enforces Business Logic, hands persistence to Repo Repo: performs ACID transactions and queries.
If your viewmodel is decoupled from any sort of framework concerns (i.e.: a POCO) You should be good since you maintain testability.
When you talk about committing data, you're talking about a unit of work. So start there:
public ActionResult AddExecutive(AddExecutiveViewModel addExecutiveViewModel)
{
// simplified; no error handling
using (var uow = new UnitOfWork()) // or use constructor injection on the controller...
{
// ???
uow.Commit();
}
return RedirectToAction(// ...
}
Now your services come out of the unit of work (because both the unit of work and the repositories share an ObjectContext
in the background; ObjectContext
is the EF's "native" unit of work). So we can fill in the // ???
:
public ActionResult AddExecutive(AddExecutiveViewModel model)
{
// simplified; no error handling
using (var uow = new UnitOfWork()) // or use constructor injection on the controller...
{
uow.EmployeeService.AddExecutive(model);
uow.Commit();
}
return RedirectToAction(// ...
}
uow.Commit()
is a thin shell around ObjectContext.SaveChanges()
. The unit of work is injected with the same ObjectContext
as the repositories. The services are EF-ignorant.
For a working (albeit in an early stage) example, see my open source repository/service project, Halfpipe.
精彩评论