Some issues about Rob Conery's repository patt

2020-02-20 05:45发布

问题:

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:

  1. I built my model as "POCOs" and put them in my "Models Layers" so they had nothing to do with the "edmx" file.
  2. Built my repositories to deal with this "POCO" model dependent on "DbContext"
  3. 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.

回答1:

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.



回答2:

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.



回答3:

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.



回答4:

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
});