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
});
Related
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.
I've been looking at the different approaches to solving the mass assignment issues with MVC as well as doing things the right way.
So far, the 2 approaches which I think are the best are below: (I have also looked at AutoMapper)
1: Value Injecter - This seems to do the job pretty well, but also relies on a third party library
2: Using the UpdateModel method and bind to a View Model interface which exposes a subset of the required properties in your domain model. http://www.codethinked.com/easy-and-safe-model-binding-in-aspnet-mvc
Before I jump in and code my whole application (without spending a week on each to find out which one I actually like) using one of the above practices, does anybody have real world experience of using these 2 methods and which one you would recommend?
in simple scenarios where you have only text fields matching strings/int properties anything will do just as well.
but when you have properties on the viewmodel that match objects in the model (FK in the DB) it gets a bit more complex, you might need to pull data from the DB for some individual props and map some property of that object to the ViewModel, stuff like that.
prodinner asp.net mvc demo application uses valueinjecter in Mapper classes, there's a pdf where this approach is explained, you can download it here: http://prodinner.codeplex.com/
General consensus from all the reading I've done on this topic is that if you're going from a Entity or Domain Model (from your database) to a View Model to show on the form feel free to use automation tools like AutoMapper or whatever your preferred tool is to automate it.
If you are however going from a Input or Form Model (the object populated via the automatic model binding) back into to your Entity or Domain Model, do not automate this. It's a slippery slope to navigate correctly and can result in your automation tool mapping over fields that were not intended/permitted. Everything I've read about this (and various implementations myself) suggest the best practice is to do this manually/explicitly. It's pretty straight forward and object initializers can make it very easy to read.
var person = new Person()
{
PersonId = model.PersonId,
FirstName = model.FirstName,
LastName= model.LastName
}
personService.UpdatePerson(person);
Something along that line.
I'm having trouble getting the design behind this correct. I'm using a repository pattern to manage my datalayer. In one of my controllers (MVC3) i am constructing a LINQ query that needs to perform a join. I have 2 questions about this:
Is is better to add a method to my repository to perform all joins, projections etc? I'm a bit hesitant about that because it would result in an ever growing contract definition on my repository?
Let's say I have a List() method in a Post repo that returns all items. I currently can't use this method in a linq (join) query because it can't convert it to a store expression. Please note that the code below use a class called repo, which holds a reference to all my repositories (post, friends) using the same context instance.
BIG EDIT:
Things are a bit more clear to me now, but i'm hoping someone will jump in here and help me get everything organised ;-). What I'm looking to do is implement a specification pattern along with my repository pattern. The problem is, i'm using POCO and my repositories are using an IContext interface which uses IObjectSets. So in the list method below, Posts is an IObjectSet and Context is an IContext interface, into which I inject my actual context.
I've been reading up and there is some very nice ready to use code, like
implementing-repository-pattern-with-ef4-poco-support and implementing-repository-pattern-with-entity-framework.
Both these examples use the objectContext in the repository. Isn't it better to abstract that out as well?
My repository:
public System.Linq.IQueryable<Post> List()
{
return this.context.Posts;
}
And in my controller method:
var friendquestions = (from q in base._repo.Post.List().OfType<Question>()
from f in _repo.Friends.List()
where f.userId == myid
where q.Author == f.friendId
select q.Id).ToArray();
The following does work however (why?):
var temp = (from q in base._repo.Post.List().OfType<Question>()
where q.Id > 6
select q.Id).ToArray();
It's basically the same problem as described here: linq-to-entities-does-not-recognize-the-method
How do I design around this? I've been reading up on Model defined functions, but i'm not sure if that's the way to go?
thanks in advance
Isn't it better to abstract that out as well?
Answer : You can look into - NCommon of Ritesh rao. It has been used IEFSession to wrap
the ObjectContext.
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.
I think I am very close to assembling an MVC repository correctly but just falling apart at the fringe. I created an MVC project with a repository and am returning data successfully, but not accurately as it pertains to DDD. Please tell me where I am incorrect in terms of strict DDD assembly. I guess if the topics are too wide, a book suggestion would be fine. I hope that I am specific enough in my question.
This was one question but I separated them for clarity: Do you create a single namespace for all repository classes called MyStore.Models? Create a repository class for each entity like Product within the Models namespace? Do you put the Pocos in their own classes in the Models namespace but not part of the Repository class itself?
I am currently using Pocos to cut out entities from Linq statements, returning groups of them within IQueryable wrappers like so. I guess here you would somehow remove the IQueryable and replace it with some type of Lazy load? How do you lazy load without being dependent on the original Linq to Sql?
public IQueryable<Product> GetProducts(...) {
return (from p in db.Products
where ...
select new myProductPoco { // Cut out a Poco from Linq
ID = p.ID,
Name = p.Name,
...
});
}
Then reference these in MVC views within the inherit page directive:
System.Web.Mvc.ViewPage<IQueryable<MyStore.Models.Product>>
However, the nested generics looks wrong. I assume this requires a re-factor. Where do you define View Model classes that contain references to Entities? Within the controller class (nested class)?
As book suggestions, try Eric Evan's Domain-Driven Design, and maybe Martin Fowler's Refactoring.
Also try Domain Driven Design Quickly produced by InfoQ. It's free to download or $30 in print.
"Domain-Driven Design Quickly was
produced by InfoQ.com, summarized
primarily by Abel Avram and with Floyd
Marinescu as managing editor. Special
thanks to Eric Evans for his support
and Vladimir Gitlevich and Dan Bergh
Johnsson for their detailed reviews.
The intention of this book is to get
an introduction to Domain-Driven
Design into as many hands as possible,
to help it become mainstream." --
InfoQ