MVC Search functionality using repository pattern - asp.net-mvc

I'm trying to build a simple Search functionality into an application using repository pattern, domain models, and a service layer.
I've searched around and haven't found anything that fits the repository pattern. I've had a quick read on the Specification method, but that doesn't look like it will fit what I require. Please read on.
A typical search would involve: Find a student that goes to college xyz, and studies subject abc, and speaks english, and... So, I'm hitting each table essentially.
I have the following layers:
Service layer
AppStudentService, AppCollegeService, ...
Business Logic Layer (BLL) which contains the following domain models:
Student, College, Subject, Language, SearchService ...
Data Access Layer (DAL) which contains the following repositories:
StudentRepository, CollegeRepository, SubjectRepository, LanguageRepository
To attack this problem, I built an AppSearchService in the Service layer. This instantiates the SearchService in the BLL, and all required repositories in the DAL.
In the BLL I built a SearchService which contains the search logic and calls a SubSearch() method on each of the repositories to fetch data for it's area, e.g. StudentRepository.SubSearch returns student(s) details. The business logic will tie up all the sub-search results together for the final search results to be returned.
I decided to break the search into a number of small queries, i.e. SubSearch methods, rather than a massive search query which would contain many joins. Using Entity Framework.
Question 1.
Each repository has it's standard methods, e.g. Add, Save, Remove, FindAll, FindBy, and a SubSearch method. Is adding my custom (non-repo) method a good idea here, or does it contaminate the repository design?
Question 2.
Would it be better put all the SubSearch methods and search logic together into a new Search class (and method) in the DAL? This way all the logic is together and doesn't require instantiating all the BLL objects and Repo objects, i.e. better performance.
Question 3.
Is what I've done a good approach for the repository pattern? If not can someone point me in the right direction, thanks.

You would be better off create a SearchRepository, that is used to search across your data layer. This will be the most efficient, because joining the results of multiple repositories together is going to be ugly, and inefficient at best. A nightmare to maintain at worst.
You don't want to perform multiple queries for a search if you don't have to. You should perform the query as a single unit. This is most efficient.

When it comes to question one and question three. This is my repository:
public interface IRepository<T>
{
IQueryable<T> List();
bool Create(T item);
bool Delete(int id);
T Get(int id);
}
That is all. Repository is for basic access and is used just to cover implementations of these functions in different database access libraries. It is generic class with generic implementation.
About question two. I am not sure what you mean, but I would create IStudentSearchService with method Search, that takes criteria object. It would use repositories (injected in constructor). You inject only repositories used by search functionality. It doesn't even matter how many of them you inject, creating repository should cost much and shouldn't make database operations. This service can have many private methods to prepare additional data for searching.

Related

Where to put complex query that returns a custom object?

I have a n-tier solution with these projects in it (simplified for this question):
Domain
Logic
Web
In the "Domain" project I have a "Repositories" namespace and each repository is mapped to a different table in the DB and query its data.
For example - the tables Customers and Orders will have the corresponding repositories - CustomersRepository and OrdersRepository.
In the Logic project I instantiate these repository objects and call their methods which actually query the DB.
Lets say I want to show a report that display some data from both tables.
This report is constructed by a collection of custom objects - IList<ReportObject>.
Now, this ReportObject object has no corresponding table in the DB and therefore has no repository object.
My question: Where should I put the part of code that actually query the DB and fetch IList<ReportObject>? Should it just be in some data controller in the Logic layer? or create another repository for the reports? Any other option?
While I think this is mainly a question of opinion, here goes:
You can create a QueryStore<ReportObject> instead of a Repository<ReportObject>. The name QueryStore is just something I came up with, it's not a coined term.
The function of such a query store would be to, well, run queries on data that is not covered by any repository. It would contain only queries and so can, for instance, easily be implemented using LINQ on top of Entity Framework querying database VIEWs for instance.
I'd put it in a custom repository (as this is not a CRUD operation). You can extend Repository (if you're working with a generic repository) and create one for the query. I wouldn't put queries in other place rather than Repositories since you'll brake the encapsulation of what Repository does. Imagine you change the database in the future, it won't be enough to change the repositories layer. Another reason to not put it there is that the logic will be spread around the application instead of being everything in just one place which simplifies debugging and improvements in the queries.
Hope it helps. Guillermo.
The repository pattern is used to encapsulate CRUD operations, but in your case you do not need any Insert or Update. I would put this into the Logic layer and access the DB directly from there.

MVC Pattern - Is this the correct approach for Repository / Unit of Work

I have been doodling and reading and just want to ensure the approach I am taking is correct. I am using MVC5 with EF, implementing the Repository and Unit of Work patterns.
EntityModel -> <- SomeRepository
SomeRepository -> <- SomeController
SomeController -> SomeViewModel
SomeViewModel -> SomeView
SomeView -> SomeController
SomeController -> <- SomeRepository
etc ..
In the controller I am planning on using something like AutoMapper to map the ViewModel to the EntityModel (and vice versa) which can then be passed to my repository / view.
Also, with this approach I am not 100% sure where my business logic should go. For instance, if I have an EntityModel for products and I wanted to add a GetAssociatedProducts method, would this go against the EntityModel or should another tier be introduced so the EntityModel is just a straightforward mapping class to the DB?
Should the ViewModel contain any logic at all? i.e Creating a Dictionary to populate a dropdown on the view based on values from the EntityModel?
I am trying to avoid the issues associated with just starting to code without thinking to much into how which is the reason for this question.
Note: I am also implementing IoC with Autofac but I don't think that's relevant at this point (saying just in case it is).
Well, you're already thinking too much.
First, since you specifically mention MVC, let me just say that the vast majority of what you're talking about is not MVC. MVC stands for Model-View-Controller. In the strictest sense, your model is the haven of all business logic for your application. The controller merely connects your model to your view, and your view merely presents the data to the client in a readable format.
Despite its name, ASP.NET MVC does not truly follow the MVC pattern. You could call it Microsoft's take on MVC. The controller and views track pretty closely (though there is some very noticeable and repugnant bleed-over, such as ViewBag). But, the "model" bit is very unclearly defined. Since, Entity Framework is integrated, most latch on to the entity and call this the model, but entities are really bad models. They're just (or at least should just be) a programmatic representation of a database table: a way for Entity Framework to take data from your table rows and put it into some structure that lets you get at it easily.
If you look at other MVC implementations such as Ruby on Rails or Django, their "model" is more of a database-backed factory. Instead of the class simply holding data returned from the database, it is itself the gateway to the database for that type. It can create itself, update itself, query itself and its colleagues, etc. This allows you to add much more robust business logic to the class than you can or should with an "entity" in C#. Because of that, the closest you can get a true MVC model is your domain or service layer, which isn't really factored in at all by default in ASP.NET MVC.
That said, though, if you're implementing a repository / unit of work pattern with Entity Framework, you're probably making a mistake. Entity Framework already does this so you don't have to. The DbContext is your Unit of Work and each DbSet is a repository. Any repository you create, dimes to dollars, will simply end up proxying your repository methods to methods on your DbSet, which is your first sign that something's not right. Now, that's not to say that a certain amount of abstraction isn't still a good idea, but go with something like a service pattern instead: something lightweight and flexible that will truly abstract logic instead of just creating a matryoshka doll of code that will only serve to make your application harder to maintain.
Finally, your view model (which is actually a rip from the MVVM pattern) should simply be whatever your view needs it to be. If your view needs a drop down list, then your view model should contain that. Whether your view model should generate it, is a slight different question that depends on the complexity of the data involved. I don't think your view model should know how to query a database, so if you need to pull the data from a database then you should let the controller handle that and just feed it to the view model. But, if it's something like a list of months, a enum structure, a numerically static list, etc., it might be appropriate for the view model to have the logic to construct that list.
UPDATE
No, they are actually implementing a repository. I'm not sure why in the world the introductory MVC articles on MSDN advocate this, but as one who fell into the same trap early on, I can say from personal experience, and many other long-time MVC developers will tell you the same, you don't want to actually follow this advice. Like I said, most of your repository methods end up just proxying to Entity Framework methods, and you end up having to add a ton of boilerplate code for each new entity. And, the further you go down the rabbit hole, the harder it is to recover, leading inevitably to some major refactoring once you finally grow tired of the repetitive code.
A service pattern is a lot simpler. There may still be some proxying for things like updates and deletes, where there's very little unique from one entity to another, but the real difference will be seen with selects. With a repository, you'd do something like the following in your controller:
repo.Posts.Where(m => m.BlogId = blog.Id && m.PublishDate <= DateTime.Now && m.Status == PostStatus.Published).OrderByDescending(o => o.PublishDate).Take(10).ToList();
While with a service you would do:
service.Posts.GetPublishedPostsForBlog(blog, limit: 10);
And all that logic about what is a "published" post, how blog is connected to post, etc., goes into your service method instead of your controller. The other big difference is that service methods should return fully-baked data, i.e. a list type rather than a queryable. The goal with a service is to return exactly what you need, while the goal with a repository is to provide an endpoint to query into.

Where do models belong in my solution?

This is the first time I'm doing a web project using MVC and I'm trying to make it based on three layers : MVC, DAL (Data Access Layer) and BLL (Business Logic Layer).
I'm also trying to use repositories and I'm doing it code-first.
Anyway I've searched a lot on the web but yet if you've got a good reference for me I'll be glad to see it .
My current project looks like this:
And here are my questions:
Where are the Product and User classes that represent tables supposed to be? It seems that I need to use them in the BLL and I don't really need them in the DAL but for the PASContext.
Where do I initiate the PASContext? In all of the examples I've seen on the internet no one made a constructor in the repository that takes 0 argument, which means that the context is not created within the repository (and I've read some reasons why like so all repositories will use one context).
If I'm trying to initiate the PASContext in the ProductBLL the compiler says it doesn't recognize it and I'm missing a reference (although I've added the needed reference and the name PASContext is marked in a blue like vs did recognize it)
PASContext is the class that is inherited from DbContext.
Here is some code to demonstrate:
public class ProductsBLL
{
private EFRepository<Product> productsRepository;
private List<Product> products;
public ProductsBLL()
{
PASContext context = new PASContext();
productsRepository = new EFRepository<Product>(context);
//LoadData();
}
About the View models, if I want, for example, to present a list of products for the client, do I need to create a ProductViewModel, get the data from ProductsBLL which has a list of Product and convert it to a list of ProductViewModel and then send it to the controller?
In addition, in the ProductController, do I only initiate ProductsBLL? I don't initiate any repository or context, right?
If someone could show me some project that uses repository, three-tier architecture and takes data from the database, transfers it to the BLL and from there to the MVC layer and using a ViewModel show it to the client it will be great.
Question 1
Where are the Product and User classes that represent tables supposed to be?
I would have these in a project that can be referenced by all other projects. That is, all other projects can depend on the solution with the models. In the case of onion architecture the models belong in the core which is at the center of the solution.
In your case I'd put them in the BLL.
Question 2
Where do I initiate the PASContext?
The reason why you don't normally see this done directly is because it's very common to use Dependency Injection or DI (What is dependency injection?)
This means that you don't need to instantiate a DbContext directly; you let the DI container do it for you. In my MVC applications the context has a PerWebRequest lifestyle.
PerWebRequest Lifestyle:
Instance of a component will be shared in scope of a single web request. The instance will be created the first time it's requested in scope of the web request.
A context is created when the request is made, used throughout the request (so all repositories gain the benefits of the first-level caching) and then the context is disposed of when the request is completed. All of it is managed by the DI container.
Question 3
do I need to create a ProductViewModel [...] ?
You generally only have one view-model to give to a view. The view should be its own object that has all of the things that the view needs in order to display everything. You suggest that you create multiple view-model objects and pass that to the view. My concern with that approach is what happens if you want to display more information for that view? Say, you want to display a single DateTime object to the user. Now you want to display one of something but you're passing many objects to the view.
Instead, separate things up. Create a single view-model and pass that to the view. If you have a part of the view that needs to display many of something, have the view call it as a child action or partial so that the view isn't doing too much.
Your approach:
A different approach:
Conclusion
If someone could show me some project that uses [...] three-tier architecture
I'm not sure about three-tier architecture. Here are some example projects that use a variety of solution architectures:
MVCForum
EFMVC
Official MVC samples
There is no single correct approach - just good and bad approaches.
I would start here. You'll get a lot more information on broad topics like this from prepared resources sources.
http://www.asp.net/mvc/tutorials/getting-started-with-aspnet-mvc3/cs/intro-to-aspnet-mvc-3.
Update
In-depth tutorials
http://www.codeproject.com/Articles/70061/Architecture-Guide-ASP-NET-MVC-Framework-N-tier-En
http://www.asp.net/mvc/tutorials/hands-on-labs/aspnet-mvc-4-models-and-data-access
http://www.asp.net/mvc/tutorials/getting-started-with-ef-5-using-mvc-4
http://www.codedigest.com/Articles/ASPNET/187_How_to_create_a_website_using_3_tier_architecture.aspx
http://www.mvcsharp.org/Basics_of_MVC_and_MVP/Default.aspx
Example Projects
http://prodinner.codeplex.com/
http://www.nopcommerce.com/
http://www.mvcsharp.org/Getting_started_with_MVCSharp/Default.aspx

Some issues about Rob Conery's repository pattern

Please read my update at the end of question after reading the answers:
I'm trying to apply repository pattern
as Rob Conery's described on
his blog under "MVC Storefront".
But I want to ask about some issues
that I had before I apply this design
pattern.
Rob made his own "Model" and used some
ORM "LINQ to SQL or Entity Framework (EF)" to map his database to
Entities.
Then he used custom Repositories which
gives IQueryable<myModel> and in
these repositories he made sort of
Mapping or "Parsing" between ORM Entities and his Model classes.
What I'm asking here:
Is it possible to make custom mapping between ORM Entities and my
model "classes" and load just
properties that I want? I hope
the point is clear.
Update For POCO
**
This is what I decided after many of suggestions and many of tries:
**
After all and with respect to Mr. Rob Conery's opinion I've got better solution as:
I built my model as "POCOs" and put them in my "Models Layers" so they had nothing to do with the "edmx" file.
Built my repositories to deal with this "POCO" model dependent on "DbContext"
Then I created a "ViewModels" to get just the information that needed by view from those repositories.
So I do not need to add one more layer to be between "EF Models" and "My Model". I just twist my model a little and force EF to deal with it.
As I see this pattern is better than Rob Conery's one.
Yes, it's possible if you're using LINQ to SQL. All you need to do is use projection to pull out the data you want into an object of your choosing. You don't need all this decoration with interfaces and whatnot - if you use a model specific to a view (which it sounds like you need) - create a ViewModel class.
Let's call it ProductSummaryView:
public class ProductSummaryView{
public string Name {get;set;}
public decimal Price {get;set;}
}
Now load it from the repository:
var products= from p in _repository.GetAllProducts
where p.Price > 100
select new ProductSummaryView {
Name=p.ProductName,
Price=p.Price
}
This will pull all products where the price > 100 and return an IQueryable. In addition, since you're only asking for two columns, only two columns will be specified in the SQL call.
Not a dodge to your question, but it's ultimately up to you to decide how your repository would work.
The high-level premise is that your controller would point to some repository interface, say IRepository<T> where T : IProduct. The implementation of which could do any number of things---load up your whole database from disk and store in memory and then parse LINQ expressions to return stuff. Or it could just return a fixed set of dummy data for testing purposes. Because you're banging away on an repository interface, then you could have any number of concrete implementations.
Now, if you're looking for a critique of Rob's specific implementation, I'm not sure that's germane to Stack Overflow.
While it's possible to populate part of an object based on a query of a subset of the columns for that object using a query (which has nothing to do with the repository pattern), that's not how things are "normally" done.
If you want to return a subset of an object, you generally create a new class with just that subset of properties. This is often (in the MVC world view) referred to as a View Model class. Then, you use a projection query to fill that new class.
You can do all of that whether you are using the repository pattern or not. I would argue there is no conflicting overlap between the two concepts.
DeferringTheLoad
Remember that IQueryable defers all the loading up to the last responsible moment. You probably won't have to load all the data using the LINQ operators to get the data you want. ; )
Respecting the dependency in domain classes in views, I will say NO. Use a ViewModel pattern for this. It's more maintainable; you could use AutoMapper to avoid the mapping problems, and they are very flexible in composite views scenarios : )
According to the new question...The answer is yes, you can. Just as Rob Conery says, use projection ; ):
var query = from p in DataContext.Persons}
select new Persons
{
firstname = p.firstname,
lastname = p.lastname
});

Is my ASP.NET MVC application structured properly?

I've been going through the tutorials (specifically ones using Linq-To-Entities) and I understand the basic concepts, however some things are giving me issues.
The tutorials usually involve only simple models and forms that only utilize basic create, update and delete statements. Mine are a little more complicated, and I'm not sure I'm going about this the right way because when it comes time to handle the relationships of a half dozen database objects, the tutorials stop helping.
For the post method, the usual way of performing CRUD operations
entities.AddToTableSet(myClass);
entities.SaveChanges();
Won't do what I want, because a fully implemented class isn't getting posted to the controller method. I may post individual fields, form collections, or multiple DTO objects and then call a method on a service or repository to take the information I receive from a form post, along with information that it needs to query for or create itself, and then from all of those things, create my database object that I can save.
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Add(int id, [Bind(Exclude = "Id")] ClassA classA,
[Bind(Exclude = "Id")]ClassB classB)
{
// Validation occurs here
if(!ModelState.IsValid)
return View();
try
{
_someRepositoryOrService.Add(id, classA, classB);
return RedirectToAction("Index", new { id = id });
}
catch(Exception ex)
{
// Logging and exception handling occurs here
}
}
public void Add(int id, ClassA classA, ClassB classB)
{
EntityA eA = new EntityA
{
// Set a bunch of properties using the two classes and
// whatever queries are needed
};
EntityB eB = new EntityB
{
// Set a bunch of properties using the two classes and
// whatever queries are needed
};
_entity.AddToEntityASet(eA);
_entity.AddToEntityBSet(eB);
_entity.SaveChanges();
}
Am I handling this correctly or am I bastardizing the framework? I never actually use an entity object directly, whenever I query for one I put the information I need in a DTO and base my Views off of that. Same goes with the creation. Is this allowed, or is my avoidance of using entities directly going against the purpose of using the framework?
Edit: I'm also worried about this approach because it requires empty constructors to properly do the LINQ queries because of this error message:
Only parameterless constructors and
initializers are supported in LINQ to
Entities.
This isn't a big deal since I rarely need logic int the constructors, but is this an issue to have no constructors and only public properties?
_someRepositoryOrService.Add(id, classA, classB);
I would say you couple your repositories with presentation layer. This shouldn't be. Your repositories should only work with entities. Next, notice how your Add method
public void Add(int id, ClassA classA, ClassB classB)
breaks Separation of Concerns (SoC). It performs two tasks:
map view data into entities
save to repository
Obviously the first step should be done in presentation layer. Consider using model binders for this. It can also help you to solve the constructors problem, since your model binders can be made aware of the construction requirements.
Check also this excellent post by Jimmy Bogard (co-author of ASP.NET MVC In Action) about ViewModels. This might help you to automate mapping. It also suggest a reversed technique - make your controllers work with entities, not ViewModels! Custom action filters and model binders are really the key to eliminate routine that that don't really belong to controllers but rather an infrastructure detail between view and controller. For example, here's how I automate entities retrival. Here's how I see what controllers should do.
The goal here is to make controllers contentrate on managing business logic, putting aside all the technical details that do not belong to your business. It's techical constraints that you talk about in this question, and you let them leak into your code. But you can use MVC tools to move the to them infrastructure level.
UPDATE: No, repositories shouldn't handle form data, that's what I mean by "coupling with presentation". Yes, repositories are in the controller, but they don't work with form data. You can (not that you should) make form work with "repositories data" - i.e. entities - and that's what most examples do, e.g. NerdDinner - but not the other way. This is because of the general rule of thumb - higher layers can be coupled with lower ones (presentation coupled with repositories and entities), but never low level should be coupled to higher ones (entities depend on repositories, repositories depend on form model, etc).
The first step should be done in the repository, that's right - except that mapping from ClassX to EntityX does not belong to that step. It's mapping concern - an infrastructure. See for example this question about mapping, but generally if you have two layers (UI and repositories) they shouldn't care about mapping - a mapper service/helper should. Beside Jimmy's blog, you can also read ASP.NET MVC In Action or simply look at their CodeCampServer for how they do mapping with IEntityMapper interfaces passed to controller constructors (note that this is more manual and less-work approach that Jimmy Bogard's AutoMapper).
One more thing. Read about Domain Driven Design, look for articles, learn from them, but you don't have to follow everything. These are guidelines, not strict solutions. See if your project can handle that, see if you can handle that, and so on. Try to apply this techniques since they're generally the excellent and approved ways of doing development, but don't take them blindly - it's better to learn along the way than to apply something you don't understand.
I would say using DTOs and wrapping the Entity Framework with your own data access methods and business layer is a great way to go. You may end up writing a lot of code, but it's a better architecture than pretending the Entity Framework generated code is your business layer.
These issues aren't really necessarily tied to ASP.NET MVC in any way. ASP.NET MVC gives basically no guidance on how to do your model / data access and most of the samples and tutorials for ASP.NET MVC are not production worthy model implementations, but really just minimal samples.
It seems like you are on the right track, keep going.
In the end, you are using Entity Framework mostly as a code generator that isn't generating very useful code and so you may want to look into other code generators or tools or frameworks that more closely match your requirements.

Resources