Showing many tables in many dropdown lists. c#, asp.net-mvc, linq2sql - asp.net-mvc

I want to use an example to explain what I want.
Assume I've following DB design:
Item (id, name, categoryID);
Category (id, name);
When user wants to create an Item (fill in form), I'll give a list of categories in a dropdownlist, and when user chooses one of the categories ASP.NET MVC will automatically bind categoryID, to the selected one. I need to present same dropdown list when editing the item with correct selected one.
Question:
But my DB is very big, and it requires around 30-40 (maybe even more) category-like tables, that contain just "id" and "name", and all tables need to be shown in dropdown list while creating some other object, and also needs to be presented while editing the object. Definitely above schema doesn't work, because it's tedious to write same logic 100 times with just different table names. (I'm using Linq2SQL)
Currently my solution is:
Make a view that's based in all such tables and in application I just call a function that construction dropdownlist from that single view. But it's still tedious to change view definition everytime I add a new table.
Do you guys think of a better solution for this tedious work, possibly using reflection or some other tecnologies.

It is not a problem "Definitely above schema doesn't work, because it's tedious to write same logic 100 times with just different table names."
If I were you, I will mark an addition interface on these class using "partial class" feature.
Then, I will write few extension method for the partial class.

If anyone interested in the solution:
I've used reflection to solve this problem.
I use reflection over DataContext to get the Table (by string name), and get its fields and construct the optionlist.

Related

Does ID belongs to view model

After working with MVC for a long time, I decided to go with MVVM. I understood the basics of the pattern and got through multiple articles that explain that MVVM is waaay better then MVC any day. And I am okay with that.
I decided to make my own app in order to set my mind correctly for logic behind MVVM. So I created basic app that does follow MVVM principles and after a while I found the problem that you see in the title.
So, basically, this is the problem. Let's say that I have one object, call it Person. Person have name and surname. But when I want to show details about that person, I will have address, phone numer etc. Because one person can have many phone numbers I will have something from API that link to the user ID.
So we came to my question. If I have some basic information about some model, and want to have detail information about that same model, where do I keep ID (or link) for that detail information? Do I have to keep it inside view controller, which would be just wrong? Or do I keep it inside view model, even if I don't use it really on user interface?
The ID also belongs to the model class. ie If you have an object Person then simply create a data class Person, which will obviously include all the members say ID, Name, Address, Number and so on. You can identify each person using the same ID as well.
The View Model need not always know about the ID. If you have a list of Person objects in view model, then you could easily map each item using the ID. Additionally if you want to have currently selected item or something, you could map it to viewmodel property of that object type ie Person. So you need not keep a PersonID field in ViewModel unless it is absolutely required for some rare cases.
Sorry, but I did not understand this : So basically in prepareForSegue method I could say something like give me from current VM object at particular index and create VM for new view that I will actually send ?
As far as simple applications are concerned, the above approach is more than enough. But in some rare cases, you may need to keep the current selected item's ID in the view model. So if you're using a list and keeping a property for selected item, it may not be the type of that list ie Person. Instead it could be the ID alone.
Hope you got the point.

single view - page - showing data from a group of normalized of tables

What I hope is a basic question,
I am designing an MVC project with the entity framework and code first and in it has a number of normalized tables that later will make up a combined view.
For example say I have a table called JOBS. This table has foreign keys for a CUSTOMER table, a STATUS table, a JOBSTYPE table.
If I want a view (a page) that displays the job with the customer, its status and its jobtype how do I manage this outcome?
In other words if I want a page that shows the job, the customer and the jobs address (sourced from the address table - itself linked via a foreign key in the customer table) how do I do the view for this?
Further, with a focus on CRUD, If I want an update page how do I display a page that has text boxes to update things like the job's address or the status which are in different tables to the actual job table.... and to press a button on the page saying "update" and each table updating automatically..
Look forward to any help clearing the confusion...
Kind Regards
Simon
Just as the question, this answer is hypothetical as well. What you can do is have a look at your page design and figure out the columns/properties you want to show from multiple tables, you then create a ViewModel for this page, then you can write a LINQ projection query to bring the results as your viewmodel.
Another other option will be to use lazy loading all linked tables and render related entities, but this this approach you have to make sure that the EF context is not disposed till the whole view has rendered.
The ViewModel and Projection approach also works well with updates and your update action will take in your view model and translate back to EF entities for updating.
For translations from ViewModel to EF Model entities and vice versa you can use automapper

Scope of viewmodels in asp.net MVC 3

I have read online that it is bad practice to use a "kitchen sink" model:
Rule #3 – The View dictates the design of the ViewModel. Only what is
required to render a View is passed in with the ViewModel.
If a Customer object has fifty properties, but one component only
shows their name, then we create a custom ViewModel type with only
those two properties.
Jimmy Bogard's subsequent explanation of how this is good, however, left me a little questioning. It'd be so easy to have my Model just contain a list of Customers, I could even use my POCO's.
So now I get to create custom little view model fragments for every page on the site? Every page that uses a Customer property would get one, but of course could not be shared since some of the information is extraneous, if one page used Age but not Name, for example. Two new mini view model classes right?
This is very time consuming, and seems like it'll lead to a million little custom view models - can someone elaborate as to the utility of this approach and why the easier approach is bad?
View model class can be used not only to transfer values, but it also defines data types (data annotations), validation rules and relations different then ones used in model. Some advantages that come to my mind right now:
There are different validation rules when you change user's password,
change his basic data or his subscription setting. It can be
complicated to define all these rules in one model class. It looks
much better and cleaner when different view models are used.
Using view model can also give you performance advantages. If you
want to display user list, you can define view model with id and name
only and use index to retrieve it from database. If you retrieved
whole objects and pass it to view, you transfer more data from
database than you need to.
You can define display, and editor templates for view models and reuse them on different pages using html helpers. It looks much worse, when you define templates for model POCOs.
If you would use your POCO objects as view models, you would essentially be showing your private objects and break the encapsulation. This in turn would make your model hard to change without altering the corresponding views.
Your data objects may contain details that are appropriate only to the data access layer. If you expose those things to the view, someone might alter those values that you did not expect to be altered and cause bugs.
Many of the same reasons as for having private members in OO languages apply to this reasoning. That being said, it's still very often broken because it's a lot of extra work to create all these "throw-away" models that only gets used once. There exists frameworks for creating these sorts of models, though the name eludes me, that can tie objects together and pick out the interesting properties only which takes away some of the drudgery from creating specific view models.
Your View Model tells the View how data should be shown. It expresses the model. I don't think its necessary to have two view models unless you have two ways to express your model. Just because you have two pages, doesn't mean you will be showing the data any different way, so I wouldn't waste time making two mini View Models when it can be in one reusable view model, Imagine if later you have a page that needs Name and Age, you would create another view model? It's absolutely silly. However, if you had two pages both showing 'Age' and it needed to be shown in a different way, then I would create another one.

How do you elegantly program ASP.NET MVC when the View needs more than one Model?

A View accepts one Model.
But I need to draw HTML input controls for two models.
An example will illustrate:
I have a screen where I add Employees.
After adding their first name, last name and so on, I need the user to choose a number of Companies the Employees could be in.
The Companies are in one table.
The Employees are in another.
And a linking table joins them.
So it seems I need to pass the Companies to the View.
Can I pass multiple models to the view?
Or do I have to do an ugly database lookup in the View to find the Companies and manually spit out HTML for checkboxes without HTML helpers?
A Model doesn't have to consist of just one object or a single collection of one type of object. It can contain many objects and/or collections of objects. It seems that the model required for your page consists of at least collections of both employees and companies. If you have no type which fits this bill in your business object abstraction then you need to create a ViewModel for this page which can do the job.
This answer may help to explain how a ViewModel fits in MVVM ViewModel vs. MVC ViewModel
This is not entirely obvious - I'm sure it is to some guru types but for the rest of us trying to work things out its a bit more interesting.
Without going into detail I see a number of ways of solving this:
You need both sets of data so you need a view specific View Model
Your model is the Employee but you can still add other data to the ViewData - so make the Employee the model and pass the company data in as well as view data but not part of the model
(You may want to do this regardless of what model you use) Render the company selection elements as a separate view - which is where things get interesting - you obviously have to pass the existing selection, or a means to identify same, to the component view but do you have to pass the company list or could you, at this point, cheat a bit (prgamatically)? My feeling is that this is a partial view and that you need to pass it a company selection model (list of companies with selection indicated) but you could in theory do RenderAction and have an action that returns a view that goes to get the company selection for the specified employee - that way the overall view never sees the company data, that becomes a separate encapsulated problem - at least in terms of loading the data.
I think in this case where you're adding the employee either tweaking the model or adding the company list as supplementary data to the ViewData is sufficient, but for editing - assuming its required - rather than inserting you want a company selection list (all the companies with flags to indicate which are currently selected) rather than just a list of companies and at that point it all gets a bit more interesting

Multiple Dynamically Populated Drop Down Lists

I've got a page which will have about ten drop down lists which are generated from my SQL database. What's the best way to populate them? I was going to use a stored procedure with LINQ to return multiple result sets, but it seems a bit overkill. Is there another way of doing it? Using HtmlHelpers or something like that?
Seeing as though everyone seems to be confused by this, I will elaborate.
This isn't to do with caching, that's not what the problem states
This isn't to do with ASP.NET controls such as DropDownList, I tagged it asp.net-mvc
This isn't to do with code-behind models, I thought that was implicitly obvious by how I tagged this question originally as ASP.NET MVC
The problem is that multiple results sets are required on the page for drop down lists (think HTML!). So I have a drop down list for your favourite breed of badger, a drop down list for how many birthdays you've had, a drop down list for how many clouds are in the sky today. All of these are dynamically populated (please note, I am joking, this is a finance system I work on). I need all of them to be on my view page, but I'd rather NOT use the IMultipleResult return type in a LINQ stored procedure to bring back multiple result sets. It just gets messy.
So in basic, I want about 10 drop down lists on my view page, all of which are populated with data from a database (which constantly change). What is the best way to get them on the view?
I would just pass the required data to the view, either in multiple ViewData dictionaries or as a special view model if you want strongly typed access. Then use HtmlHelper.DropDownList() to display the actual drop downs.
Weakly typed solution
Controller
ViewData["Data1"] = SomeRepository.GetList();
ViewData["Data2"] = SomeRepositoty.GetList();
return View();
View
<%= Html.DropDownList("Data1") %>
<%= Html.DropDownList("Data2") %>
Strongly typed solution
View model
public class DataViewModel
{
public IEnumerable<string> Data1 { get; set; }
public IEnumerable<string> Data2 { get; set;}
}
Controller
var model = SomeRepository.GetModel(); // returns an instance of DataViewModel
return View(model);
View
<%= Html.DropDownList("Data1", new SelectList(Model.Data1)) %>
<%= Html.DropDownList("Data2", new SelectList(Model.Data2)) %>
It depends on the data, if the data in the database is not updated that often, then you could have a process that creates XML files once a day. Then use the XML files as the source to the dropdowns, this would speed up the application and limit the calls to the database server.
This is really a question of data management, not anything to do with HtmlHelpers until you get to the very pointy end of things. Anyhow, the first thing I would ask myself is "how is this data updated and what kind of filtering do I need?"
If this list is pretty much constant, then you could go for a bit of caching.
If this list is pretty fluid, then just pull it out of the database as needed and be done with it. Worry about caching if your DB box starts melting.
Either way you probably want to wrap things up in some sort of LookupService class, but there isn't enough to go on to make any more specific recommendations.
I second Wyatt's recommendation about grabbing from the DB each time if the list is fluid.
However, I'm doing a similar thing (with 10+ dropdowns on each page, all very static... the values will rarely change).
The first version of the application had a helper method for each dropdown list (about 20 total by the end of the project) that grabbed from the respective tables and cached via another helper. Before I started caching, there was no db context available for the view (i created it in the controller and didn't pass it), each dropdown had to create a new connection. This got noticeably slow. Plus, I had some problems with my caching routines, and saving them with 20 magic strings in the cache, etc. Also, I had a separate querying object where I had to manually build the relationships, and having to create the 20 relationships for inner joins was a pain.
So... my new version:
I'm using a single "selectables" table. There's a PK, and a "selectable type" (which I have to admit is a string). There's a selectables enumerable, which makes things a bit cleaner. There's a main getAllSelectables() method that looks for the entire result set in the cach (and gets all rows from the db if its not in the cache) and returns it. Then there's a getSelectables(enum) that grabs out only the relevant values, and a third function getSelectListItems(enum) that calls getSelectables(enum) and returns a ienumerable for the mvc helper function.
Hope that helps,
James

Resources