What is the preferred model configuration for CRUD?
I am attempting to perform crud operations within a simple content management website. In attempting to create my CRUD views for the entering of a piece of content, there are several drop-downs that need to be populated, and in the case of an edit operation they need to have specific values pre-selected. I have been reading a textbook on it and absorbing as much as I can through articles on the web, but I'm having trouble in determining where the best place is for the information belonging to these drop-downs. I could easily create model classes to identify them, and then I would have an option of either getting the data to fill them开发者_如何学C one at a time or have this information populated as properties in my content model class so that the value of the class is selected, but an IEnumerable property would be available to bind to directly.
Either way seems to work with using templates to create the drop-downs, but I'm trying to eliminate some of the "Select N+1" issues of retrieving these things individually, but I also don't want to pack my model full of too much junk that really doesn't belong there as considered against the MVC architecture.
So the basic question is: Does supporting information like drop-downs, filters, etc belong as sub-classes in the primary model class or should these be retrieved individually and presented as separate items by themselves? Or is there some other aspect to the architecture that should be used and I'm just missing the boat completely?
Articles, links, redirects are all welcomed. I have Googled this, and what I have found has either not answered this question or the answer is hiding within the mass of results.
example: Books and Authors entities when creating a new book in a view, you need a select control that has its options populated as all the available authors.
the Book model should be clean and contain only the relevant fields e.g. Title, Author
the controller should have an IAuthorRepository _authorRepository; field that could have been set by a DependencyResolver or manually in the controllers constructor. IAuthorRepository would have a method such as IEnumerable GetAvailableAuthors();
the [HttpGet] Create() action could return an empty Book model directly and then stuff the _authorRepository into the dynamic ViewBag. ViewBag.AuthorRepository = _authorRepository;
The view would then pass the ViewBag.AuthorRepository to a partial view or a custom editor. Your model is kept clean in this scenario.
Some people don't like any use of ViewBag.Xxx (or ViewData["Xxx"]) because it's less than perfect MVC. I've seen examples that would Create a new type like BookViewModel. BookViewModel would then contain Book and IAuthorRepository in itself. the [HttpGet] Create() action would then return a BookViewModel object and the view would render its Author Select partial view by passing it the model.AuthorRepository instead of the ViewBag.AuthorRepository. This sort of starts to look more like MVVM here rather than MVC. Your instinct to keep any such collections or repositories out of the actual model (Book) is right. A clean model is very important and will give you the most flexibility in any pattern.
Not sure if this is the thing you are after but I use my own class library called Web.Shared which holds all my helper methods. I have a SelectListHelper class which I use to populate all my dropdownlists. That way my code is seperated from the main domain model and can be reused through this and any other MVC app which is part of my solution.
// Return days of the month for a dropdownlist
public static class SelectListHelper
{
public static SelectList DayList()
{
return NumberList(1, 31);
}
}
// Use in view
@Html.DropDownListFor(m => m.Day, SelectListHelper.DayList())
// Another one for selecting genders
public static SelectList GenderList(string selectedValue = null)
{
IList<KeyValuePair<string, string>> genders = new List<KeyValuePair<string, string>>();
genders.Insert(0, new KeyValuePair<string, string>("F", "Female"));
genders.Insert(0, new KeyValuePair<string, string>("M", "Male"));
genders.Insert(0, new KeyValuePair<string, string>("", "Choose Gender"));
return new SelectList(genders, "Key", "Value", selectedValue);
}
// Use in my edit view
@Html.DropDownListFor(m => m.Gender, SelectListHelper.GenderList())
Failing this take a look at MVC Scaffolding for creating data bound CRUD Views.
I agree with Tion's answer but my response can't fit in a comment.
First, the simple solution if you're using NHibernate: you can setup batching on has-many collections to load many entities in one query (instead of N!). We use a batch size of 100 with very noticeable performance gains. This won't help if you're just loading everything from a single table.
Now the trickier, but still very worthwhile solution.
If you have fairly static content that gets queried often (drop down lists, account name lookups, etc) you should really think about caching it in memory. If you're using IOC it's very easy to swap in a CachingRepository implementation for IRepsoitory<>. At my company we borrowed FubuCache from FubuMVC, but I think it's just a dictionary behind the scenes. If you have a server farm or multiple servers accessing the same data, you can use Memcached to share data.
The important thing about caching is knowing when to clear it. (ie, reload content from the database.) For us that means
1) every 5 minutes no matter what (other applications interact with the db so we need to pick up their changes. 2) any time an entity is inserted or updated we clear all the relevant caches.
Since most of our applications are reporting over large datasets with many joins we cache nearly everything. As long as your server has enough RAM you'll be fine.
ps http://axisofeval.blogspot.com/2010/11/numbers-everybody-should-know.html
精彩评论