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.
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 use MVC4 and entity framework 5 in my project and I've lots of tables. As a rule of our project, we don't delete any records from database, each record has a isActive field and if that field is false, then we consider it deleted. I wanted to write an extension method to get active records and after some googling I wrote this:
public static IQueryable<Company> GetAll(this IQueryable<Company> source)
{
return source.Where(p => p.isActive);
}
Now I can use my extension method to get only active records like
Context db = new Context();
db.Company.GetAll();
But let's say I've 50+ tables in my database, is it a good approach to write the same extension method for each of my tables. Is there a better way to write a only one GetAll() extension method for all of our tables? Actually I'm not even sure if is it right way to use extension methods for this instance?
Could somebody please help me and show me the right way? I appreciate if you help with code examples.
It depends on how you are using Entity Framework, if you are depending on the normal generator (and I think you do), your case gets harder and I never had a similar case study. But, if you use normal POCO classes generator, you can use a base class let's call it CEntity which is a base class for each of your other classes (tables).
Are we there yet? No, to continue with this, I prefer to use the Repository Pattern, and you can make that repository generic (CEntity), for example:
public class Repository<CEntity> where CEntity : class
{
public IQueryable<CEntity> GetAll()
{
return source.Where(p => p.isActive);
}
}
And this is how to use it:
Repository<Company> com = new Repository<Company>();
Repository<Employee> emp = new Repository<Employee>();
var coms = com.GetAll(); // will get all ACTIVE companies
var emps = emp.GetAll(); // will get all ACTIVE employees
This is off the top of my head, if you had any other problems, put them as comments, glad to help.
Just as a point of interest, this is exactly how I implement my data layers, and i think its awesome :)
I also jam a repository in the middle as well but the general concept should work with or without.
Here's some working code examples of how I use this method in my blog for some similar use cases.
https://github.com/lukemcgregor/StaticVoid.Blog/blob/master/Blog/Data/Entities/Post/PostRepositoryExtensions.cs
I've found that it makes some pretty elegant code while still not restricting what you can do too much. Like i said, i think this method is awesome and really recommend its usage.
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
});
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
Reviewing Conery's storefront, and I dont understand why he used Linqs auto-generated classes (ie Order class) and then he has another Order class defined that is not a partial class. WHen using repository pattern should one manually create the classes, and disregard Datacontext altogether?
If you don't decouple your front end from the linq classes using an intermediary class, you can't control with the data context gets garbage collected. Typically with data context types of instances you want to rid of them as soon as you're done using them. Here's how you might want to do this with the linq to sql context:
using (MyDataContext data = new MyDataContext())
{
SomeThing thing = data.Things(t => t.ID == 1);
return thing;
}
... the MyDataContext instance is gone
With the "using" block, you're disposing of the instance of MYDataContext at the last "}". However, if you do this you'll get an error then trying to use "thing" because the data context instance is gone. If you don't dispose of the data context, it's left hanging around until it's eventually garbage collected.
If you introduce an intermediary class to decouple the linq to sql code from the calling app you can still get rid of your data context instance and return the same data (just in a different object):
using (MyDataContext data = new MyDataContext())
{
SomeThing thing = data.Things(t => t.ID == 1);
SometThingElse otherThing = ConvertSomethingToSomethingElse(thing);
return otherThing;
}
... the MyDataContext instance is gone
Hope that helps.
Rob has answered on this question in one of his show.
He Using POCO classes to be aware from all dataaccess classes. For example when he change LINQ-to-SQL to NHibernate all he will need to do i change his "mappings" in his filters, and he will not have to make any changes in bussiness logic.
He said in one of his recent videos he doesn't like the way LINQ to SQL does mapping. I agree though I think it is complete overkill.
I'd say you're not breaking any major design patterns as long as you're sticking to the repository pattern itself. I think it's a matter of choice to have 2 sets of classesa, allbeit a bad one, still a choice.