I am working on asp.net mvc5 web application and I am using entity Framework as the data access layer. Whenever I start implementing new requirement , I always get stuck on how I should design the interaction between action methods and repository classes. . for example let say I have the following Post Create action method:-
Public ActionResult CreateStudent (Student student)
{
repository.AddStudent(student);
repository.Save();
return RedirectToAction(“Index”);
}
And here is the repository
Public class Repository {
Public Void AddStudent (Student student)
{
// + Initiate a pending Audit Object
//+ Create new Person object and retrieve its ID
SaveChanges();
//+ create new Student and assign it to the created Person
// + Complete Audit object
}
This is how I currently implement the interactions, less calls from action method to repository, and i have somehow large repository methods.
But as another approach I can have more calls to the repository methods, and have smaller repository methods comparing to the first approach such as:-
Public ActionResult CreateStudent (Student student)
{
var audit = repository.IntiateAudit(student);
var person = repository.AddPerson(student);
repository.Save();
var student2 = repository.AddStudent(person);
repository.CompleteAudit(audit);
repository.Save();
return RedirectToAction(“Index”);
}
And here is the repository
Public class Repository {
Public Audit IntiateAudit(Student student)
{
//implementation goes here…
Return Audit;
}
Public Person AddPerson (Student student)
{//implementation goes here…
Return Person
}
Public Student AddStudent (Person person)
{//implementation goes here…
Return student;
}
so generally speaking which approach is considered better;either having smaller repository methods and multiple calls , OR large repository methods with less calls to the repository methods ?
I wouldn't put those individual repository calls in the controller as you generally shouldn't really be responsible for the implementation details of creating a student there.
I would have the controller implement a Student Service and have a CreateStudent method on the service. The service would implement the repository(s) or context(s) it needs to deal with orchestrating the logic needed.
If you have a service you can encapsulate logic which spans repositories and hide the details from the controller which should not act as the model.
Services are easily reusable - e.g. maybe later you'll add an API layer to your app which can also create students. You don't want to replicate code to do that.
Accessors.
You could also create a data accessor layer which would hide the repositories and UoW.
Actually I went through building an MVC 4 portal where I put everything inside the MVC application, for example my business logic in the controllers, my data access in the model, and my presentation layer in the view.
This approach would be suitable for small projects where you don't have that much business logic and a small data model, using this pattern you would put all the calls inside the controller and areas section, you would have helper classes to do some business logic, the model will hold only data definitions, and the view will list the data.
A new approach which I love more and I work toward in my new systems is to deal with the MVC application as a presentation layer, where the controller will do the needed preparation and format to send the data(model) to the view to be presented.
In this case you need a new BLL (class library or a service) which will hold all your business, and DAL (class library or service) to hold all your data access work.
In this case the MVC application will do minimal calls to the BLL to get whatever data/logic processing, and the BLL will do the same if it needs to get some data from the DAL.
Related
On a 3 tier application, I am using my business entities to generate the dbSets on my dbContext.
On business layer:
public class User
{
string name {get;set;}
}
On the data layer:
public context:DbContext
{
public DbSet<User> Users {get;set;}
}
My question then is how can I encapsulate logic on the entities? I could use extension methods, but I also want some properties, and I don't want them to leak outside the domain layer.
With this type of architecture, it's best to create Interactors that contain all the business logic. That way your domain models (such as User) can be very lightweight.
There are two common ways to go about create Interactors. One way is to create a Service object. The service can offer all use cases and perform all business logic. This approach works better for simple domain models and for small/medium applications.
Service Interactor Example:
public class UserService
{
public void ChangeUsername(User user, string name)
{
... business logic ...
}
}
Another common way to encapsulate business logic is to create an object per use case. Whenever you add a new operation, simply create a new class. This requires more initial work and a better grasp of enterprise architecture, but results in a very scalable solution.
Use Case Interactor Example:
public class ChangeUsernameOperation
{
public void ChangeUsernameOperation(User user, string name)
{
... business logic ...
}
}
I asked a question about ASP.NET MVC Generic Controller and this answer shows a controller like this:
public abstract class GenericController<T>
where T : class
{
public virtual ActionResult Details(int id)
{
var model = _repository.Set<T>().Find(id);
return View(model);
}
}
Which can be implemented like this.
public class FooController : GenericController<Foo>
{
}
Now when someone requests /Foo/Details/42, the entitiy is pulled from the _repository's Set<Foo>(), without having to write anything for that in the FooController.
The way he explain that is good but think i want to develop a generic controller for product and customer where i will not use EF to load product & customer model rather use MS data access application block.
public abstract class GenericController<T>
where T : class
{
public virtual ActionResult Details(int id)
{
//var model = _repository.Set<T>().Find(id);
var model =customer.load(id);
or
var model =product.load(id);
return View(model);
}
}
So when request comes like /Customer/Details/42 or /product/Details/11 then generic controller's details method will call but how we can detect that request comes from which controller and accordingly instantiate right class to load right model.
If request comes for Customer then I need to load customer details from detail action method or if request comes for Product then I need to load Product details from detail action method of generic controller.
How do I use generics to get the dataset of type T with the Entity Framework Data block?
You may create a set of repositories for working with your entities, like CustomerRepository, ProductRepository from base interface like
public interface IBaseRepository
{
T Get<T>(int id);
void Save<T>(T entity);
}
and then extend your base controller class with repository type and its instance with any of DI frameworks
public abstract class GenericController<T, TRepo>
where T : class
where TRepo : IBaseRepository, new()
{
private IBaseRepository repository;
public GenericController()
{
repository = new TRepo();
}
public virtual ActionResult Details(int id)
{
var model =repository.Get<T>(id);
return View(model);
}
}
Example for CustomerController
public class CustomerController : GenericController<Customer, CustomerRepository>
{
}
where CustomerRepository:
public class CustomerRepository : IBaseRepository
{
public T Get <T>(int id)
{
// load data from DB
return new Customer();
}
}
I don't think it's wise to place data-access and business logic like this in controllers when your application's size and complexity grows beyond a certain point. You should create repositories which handle the data-access and abstract the technology (EF, plain ADO.NET, etc.) away from the consumers. You could use these repositories in your controller, but that would mean that your controllers still contain business logic which you don't want. Controllers should be thin.
What I did was creating a service layer between my repositories and controllers which contain the business logic and delegate data-access to the repositories. I use these services in my controllers to fetch my domain models where I map them to view models. You're gonna want an Inversion of Control container to 'glue' the layers together and to provide loose coupling between them.
A search for 'c# mvc repository and service pattern' will result in loads of examples. I found this post a good one, except for the fact that he returns view models from his services rather than domain models.
This is just my 2 cents, please keep in mind that all of the above only counts when your have a 'mid-range' application and not a typical tutorial/try-out website.
Given my disclaimers in the other question and my comments here explaining why this isn't an ultimate solution, I'll try to give a more concrete implementation:
public abstract class GenericController<T> : Controller
where T : class
{
protected YourEFContext _dataSource;
public GenericController()
{
_dataSource = new YourEFContext();
}
public virtual ActionResult Details(int id)
{
var model = _dataSource.Set<T>().Find(id);
return View(model);
}
}
public class CustomerController : GenericController<Customer>
{
}
This is all code that is needed to let /Customers/Details/42 load customer with ID 42 be loaded from the Entity Framework context. The "generic" part is solved by Entity Framework's DbContext.Set<T>() method, which returns the DbSet<TEntity> for the appropriate entity, in this case DbSet<Customer> which you can query.
That being said, there are many problems with actually using this code:
You don't want to let your controller know about your data access. As you see, a YourEFContext property is used in the controller, tightly coupling it with Entity Framework. You'll want to abstract this away in a repository pattern.
You don't want your controller to instantiate its data access, this should be injected.
You don't want your controller to return database entities. You're looking for ViewModels and a Mapper.
You don't want your controller to do data access. Move the data access in a service layer that also contains your business logic, abstract it again through a repository pattern.
Now your question actually is "Does the Enterprise Library Data Block have a method like GetDataSet<T>", so you don't have to refer to customer and product in your generic controller, but unfortunately I can't find that as I haven't used EntLib for a few years. It would help if you show the code you currently use to access your database.
The ultimate goal you're looking for:
[ MVC ] <=> [ Service ] <=> [ Repository ]
View ViewModel Controller BusinessModel BusinessLogic DataModel Database
Your controller only talks to your service to Create/Read/Update/Delete BusinessModels, and performs the mapping between ViewModels and BusinessModels (at <=>). The service contains the business logic and business model (DataContacts when using WCF) and in turn maps (<=>) to and from DataModels and talks to your repository to persist your models.
I understand this can be a bit much to grasp at once, and that's probably why most ASP.NET MVC tutorials start with all three tiers in one application. Take a look at ProDinner for a more proper approach.
As I am fairly new to web application development I am currently having some difficulty in implementing some testing functionality.
As part of the project I am currently working (An MVC 3 Web App for processing payments) I have been asked to create a testmode which can be accessed through the URL in this manner:
http://websiteurl?testmode=1
The idea behind this is that when one of the development team adds the testmode parameter to the URL a set of form values are auto generated in order to save time on entering data each time the application is tested.
Currently I have an if statement in the controller which uses Request.QueryString to set the parameter below is the code that I am currently using:
if (Request.QueryString.AllKey.Contains("tm"))
{
if (Request.QueryString["tm"] == 1)
{
insert values to be generated
}
}
Given the context what if any would be the best method of achieving this?
Would it be possible to using a mocking framework such as Moq or RhinoMocks to create a fake repository rather than retrieving results from a database or would it be better to have test data preloaded in the database?
To start with I would encapsulate your "TestMode" check.
I would create a base controller and and add the following property:
// I would consider retrieving this from web.config
protected string testModeKey = "tm";
public bool IsTestContext
{
get
{
return Request.QueryString[testModeKey] != null;
}
}
Alternatively, consider writing an extension method for the HttpRequest:
public static bool IsTestContext(this HttpRequest request, string testModeKey = "tm")
{
request.QueryString[testModeKey] != null;
}
This is out of the way. Let's think how we could insert the values. I'm making few assumptions here, but I'd be interested in making controller unit-testable.
I'm assuming that your data is returned from some IDataRepository and you have two implementations of repository: FakeDataRepository and ReadDataRepository.
You could then write a factory or a simple ifelse statement to decide which repository to use.
IDataRepository DataRepository { get; set; }
if (Request.IsTestContext)
DataRepository = new FakeDataRepository();
else
DataRepository = new RealDataRepository();
This would work for what you want it to do, but it's not a good way forward in my opinion. I would look into unit testing your controllers. Can you provide more details on what you would like to test, as I'm making quite a few assumptions and guesses here?
So that you have a few details on how the application is currently laid out I have provided details below:
The basic structure of the application follow the project silk template, breaking down the application into Business Logic, Data Tier, Presentation and Unit Tests, the controller that I am implementing this testmode in already inherits from a base controller which currently contains an implementation of the Microsoft.Practices.ServiceLocation pattern.
the service locator access four services found in the Business Logic Domain project, three of these access repositories that contain values for three drop down lists the fourth access an implementation of the transaction service for the payment solution (SagePay) that has been integrated into the app this uses the SagePayMvc.dll.
All of the repositories inherit from a Base Repository I currently have six repositories that inherit from this base, three again are for populating drop down lists the other three store information on Students, Card Holders and Order Details the testmode is basically accessing the Student Repository which is currently to populate a student details form currently the Card Holder details can be populated using JQuery.
There are two sets of models one set in the Business Logic and the other in the Data Tier, with the model validation being defined in thee Business Logic Domain.
The View Model through which I access the models is currently using the Domain Model.
In order to create the repositories I am using the Entity Framework Code First approach, it currently creates the repositories as a database where the tables correspond to each of the defined models.
The purpose of the this testmode is to quickly populate the non-unique form fields (I currently have some logic implemented that stop Students from entering a name that already exists) so that when other members of the team are using the application they can quickly assess if the application is working it is particularly for the design team as they apply styling to application.
I currently have one Test Class setup which is testing the assertion that the Student Repository can create a new student the data I have defined in here access a fake repository defined using Moq.
I am trying to create a small personal project which uses EF to handle data access. My project architecture has a UI layer, a service layer, a business layer and a data access layer. The EF is contained within the DAL. I don't think it's right to then make reference to my DAL, from my UI. So I want to create custom classes for 'business objects' which is shared between all my layers.
Example: I have a User table. EF creates a User entity. I have a method to maybe GetListOfUsers(). That, in the presentation, shouldn't reply on a List, as the UI then has a direct link to the DAL. I need to maybe have a method exposed in the DAL to maybe be something like:
List<MyUserObject> GetListOfUsers();
That would then call my internal method which would GetListOfUsers which returns a list of user entities, and then transforms them into my MyUserObejcts, which is then passed back through the layers to my UI.
Is that correct design? I don't feel the UI, or business layer for that matter, should have any knowledge of the entity framework.
What this may mean, though, is maybe I need a 'Transformation layer' between my DAL and my Business layer, which transforms my entities into my custom objects?
Edit:
Here is an example of what I am doing:
I have a data access project, which will contain the Entity Framework. In this project, I will have a method to get me a list of states.
public class DataAccessor
{
taskerEntities te = new taskerEntities();
public List<StateObject> GetStates()
{
var transformer = new Transformer();
var items = (from s in te.r_state select s).ToList();
var states = new List<StateObject>();
foreach (var rState in items)
{
var s = transformer.State(rState);
states.Add(s);
}
return states;
}
}
My UI/Business/Service projects mustn't know about entity framework objects. It, instead, must know about my custom built State objects. So, I have a Shared Library project, containing my custom built objects:
namespace SharedLib
{
public class StateObject
{
public int stateId { get; set; }
public string description { get; set; }
public Boolean isDefault { get; set; }
}
}
So, my DAL get's the items into a list of Entity objects, and then I pass them through my transformation method, to make them into custom buily objects. The tranformation takes an EF object, and outputs a custom object.
public class Transformer
{
public StateObject State (r_state state)
{
var s = new StateObject
{
description = state.description,
isDefault = state.is_default,
stateId = state.state_id
};
return s;
}
}
This seems to work. But is it a valid pattern?
So, at some point, your UI will have to work with the data and business objects that you have. It's a fact of life. You could try to abstract farther, but that would only succeed in the interaction being deferred elsewhere.
I agree that business processes should stand alone from the UI. I also agree that your UI should not directly act with how you access your data. What have you suggested (something along the lines of "GetListOfUsers()") is known as the Repository Pattern.
The purpose of the repository pattern is to:
separate the logic that retrieves the data and maps it to the entity
model from the business logic that acts on the model. The business
logic should be agnostic to the type of data that comprises the data
source layer
My recommendation is to use the Repository Pattern to hide HOW you're accessing your data (and, allow a better separation of concerns) and just be concerned with the fact that you "just want a list of users" or you "just want to calculate the sum of all time sheets" or whatever it is that you want your application to actually focus on. Read the link for a more detailed description.
First, do you really need all that layers in your 'small personal project'?
Second, I think your suggested architecture is a bit unclear.
If I get you right, you want to decouple your UI from your DAL. For that purpose you can for example extract interface of MyUserObject (defined in DAL obviously) class, lets call it IMyUserObject, and instead of referencing DAL from UI, reference some abstract project, where all types are data-agnostic. Also, I suggest that you'd have some service layer which would provide your presentation layer (UI) with concrete objects. If you utilize MVC you can have a link to services from your controller class. Service layer in turn can use Repository or some other technique to deal with DAL (it depends on the complexity you choose)
Considering transformation layer, I think people deal with mapping from one type to another when they have one simple model (DTO) to communicate with DB, another one - domain model, that deals with all the subtleties of business logic, and another one - presentational model, that is suited best to let user interact with. Such layering separates concerns to good measure, making each task simpler, but making app more complicated in general.
So you may end having MyUserObjectDTO, MyUserObject and MyUserObjectView and some mapping or transformation btw them.
I am reading up about service layers and repositories. Now I am wondering if a service layer must wrap the dal. I am working a lot with repositories and the MVP pattern. The presenters now holds the business logic. But the more I think about it, it is not a logic place to put the business logic in the presenter nor the data access layer. So this is the point the service layer comes in.
But does the presenter now talks to the service layer? And is it 'allowed' that the presenter can access the repositories? Or should everything go via the service layer? In the latter case, the service layer is just a middleman:
MyFooService:
public List<Foo> GetAllFoo()
{
var listFoo = new FooRepository().GetAll().TiList();
return listFoo;
}
Presenter:
public List<Foo> GetAllFoo()
{
var listFoo = new MyFooService().GetAllFoo();
return listFoo;
}
Is the good way to go? Or is it 'allowed' that the presenter directly calls the repository?
Sometimes you do not need to over engineer things or force into patterns when you don't need them.
The DAL, is itself sorta a special service to access data.
Typically your service layer will do stuff not related directly to your data. Think things like PaymentService, AnalyticsService etc things like that, that can be separated into a re-usable component.
Lets say you needed to share a post on to all social media, you could put this into a service that does the job of signing into the right social media and posting:
MySocialBlastService : ISocialService
{
void ShareToTwitter() { }
void ShareToFacebook(){ }
}
Now from your controller/presenter you can call this service.
public ActionResult ShareLink(string link..) //asp.net-mvc method as an example
{// maybe you could use dependency injection here to get ISocialService
ISocialService _service;
_service.ShareToTwitter(link);
}
Just so you're clear on what business logic is:
MathService
{
int Add(a,b) { ..} //this is business logic
}
Its some stuff you need to do, and you can do it without touching an interface, this needs to be encapsulated. More real world examples are SecurityService.ResetPassword()
When you call this from the controller:
You could use the business logic of adding in a web app, or in a windows app, and get the inputs from the user through some interface. How you do that is controller logic.
public ActionResult Calculate(int a, int b)//comes from webpage
{
//this is controller logic
int ret = MathService.Add(a,b);
//logic to send ret back
//to some other page to display to user.
}
I would say that if you are doing "serious" middle to big scale development it is better not to put business logic into your presentation layer. How you isolate it is another question.
On the other side if you use something like Entity Framework or NHibernate I would only create repositories if it is really necessary to abstract data access, for using mocks when testing, for example.