Supplying the model with varying amounts of data from database - asp.net-mvc

Supposed I have an online store and a model User, which contains a whole bunch of parameters (First Name, Last Name, an Address object, ProductCategoryAccess object etc.)
The way it's currently set up is the constructor accepts an Id and populates the entire class with data from the database.
But what if I don't need all that data? For example, if I have a view that just lists users, I'd have to create a list of Users, with each of them needlessly querying the database for information that I don't need (Address, ProductCategoryAccess, etc).
What's the best way of handling this? Do I create a bunch of different classes, with only the parameters I need for various situations? Do I create one User class, but with different "setter" methods, which will use different queries to populate only certain parameters?

Are you using any ORM tools to get the data? If yes, then you could use lazy binding to retrieve only elements that you need.
If you are directly querying the db, then dividing it across different methods with queries should do the trick.
What are the different situations you need to account for?

If you only wish to select certain properties from your user database record then you can use projections to bind the records into a data transfer object that contains only the properties you need for any given page.
For instance, if you needed properties for an edit user page then your query (I assume you're using Entity Framework?) would look something like this:
this.userContext.Users.Where(y => y.UserId == userId).Select(x => new UserEditDto {
FirstName = x.FirstName,
Surname = x.Surname,
EmailAddress = x.EmailAddress
}).FirstOrDefault();
What this will do is build a LINQ query against the database that selects only the properties specified within the select part of the LINQ statements. In fact, if you were to remove the FirstOfDefault() method and stick a breakpoint in you'd be able to see the SQL generated by that statement would look a little something like:
SELECT FirstName, Surname, EmailAddress FROM users WHERE userId = 1;
It's only when you call .FirstOrDefault() does the LINQ provider execute the query against the database and return the result.
From here you're able to return your DTO to your service layer or your controller to send it to a view within a view model. You can then rinse and repeat this same type of query for other possible data transfer objects and views that require certain data.

Related

Performance implications : Entity table reference vs List of that table reference

I am using entity framework and developing an architecture for application with remote data access. Coming back to point, i query the database for one record (say on the basis of itemcode). Now the resultset i will get whether i should return it as List or collection or simple as an object of entity. I am using entity object but my boss is saying i should use List. He thought , returning result as an entity with return whole table structure also. Quick suggestion would be appreciated.
List<Employee> lstemployee = GetRecordByCode(itemCode)
or
Employee emp = GetRecordByCode(itemCode)
What's the difference? If itemCode is a unique key you will either get one Employee object or a list containing the same one Employee object. You will never return the whole table. That will only happen if within GetRecordByCode you do something like context.Employees.ToList() without any Where filter before the ToList().
If itemCode is not unique you even have to use a list.

Model design in ASP.NET MVC

I am constanstly having problems with model design in MVC. Mostly all of my projects require some entities that are to be created, edited and deleted. Most of these entities have some common properties like creation date, modified date, author, modified by and in some cases even more descriptive properties are common. Because of that I have one single DB table to store them. For instance, Documents table and we store Invoices, Quotations and other business documents in it. I am using Entity Framework v4 for ORM, where we eventually end up with the Document entity.
How do I modify this entity or do I create a separate DocumentViewModel class for it to support multiple document types with common properties (so some form of inheritance or interface implementation should be implemented)? Besides identifying different document types I also need to have some types to have different Data Annotation rules (attributes).
For instance, Document table has PayDate column. Document type Invoice requires PayDate to be provided but document type Quotation does not.
This is the one single problem I am facing over and over with MVC and so far I've been handling it different every time but cannot decide how to properly handle it to achieve the maximum application maintainability and ease of development.
Have you considered making Documents entity abstract?
From the DB side, you will have Documents table containing just the fields shared by all Invoices/Quoations/etc. This field will have an IDENTITY PK - e.g DocId.
In the other tables, additional meta-data specific to that document can be stored, and the PK is a (non-IDENTITY) field DocId, which is also a FK to the Documents table.
On the EF side, Documents becomes an abstract entity, and the other entities inherit from this entity. This allows a nice OO paradigm to exist, and makes your code more robust.
We are currently using this scheme (EF4/SQL Server).
Your scenario sounds very similar to ours - consider using Abstract Classes.
EDIT
Thought i'd add a bit more info to how i've actually implemented this scenario, to put you on the right track.
As the comments to your Q state, we have little knowledge of your domain, therefore it's hard to make informed opinions. Personally, i chose to make my entity abstract, because certain functionality required a "mixed-bag" of items to be returned in one hit. There are other ways to do this of course (such as a stored procedure), but this allows a nice fluent interface between my UI (which is MVC by the way) and my service layer.
Works like this - here's how i get a single Post:
// var is strongly-typed to a "Post"
var somePost = repository.FindSingle(10);
Here's how i get a mixed-bag of Posts:
// var is strongly-typed to a "ICollection<Post>".
// "Title" is a property on my "Post" abstract POCO
var mixedBagOfPosts = repository.FindAll<Post>(p => p.Title = "Some Title");
Here's how i get a collection of "Reviews" (child of Post):
// var is strongly-typed to a "ICollection<Review>"
// "Rating" is a property on my "Review" POCO (derived from Post)
var reviews = repository.FindAll<Review>(r => r.Rating == 5.00);
The kicker is my repository is implemented with generics, and the type parameter ensures type-safety:
ICollection<T> FindAll<T>(Expression<Func<T,bool>> predicate) where T : Post
And it's implemented like this:
return myContext.Posts.OfType<T>.Where(predicate).ToList();
The OfType causes an inner join to the T (which is the child table), so only those records are returned.
Of course, i also have a service layer mediating between my UI and repository, but this should get you on the right track.
Also, you don't have to go with the whole Expression-predicate thing, i like this because it minimizes the number of methods on my interface, and gives full querying power to my controllers, whilst ensuring the queries are deferred to the point of the service layer, but not further.
If you don't like this, you could of course have regular parameters (string title, etc).
As i said, this architecture suited my domain requirements, so it may not necessarily suit yours, but hopefully it gives you some insight.
You can put a table in your EF model many times and just rename them to the entities you need. Just delete the columns you dont need from those.
For example, put in a Documents entity... now rename it to Invoice. Now add another one, and name it Quotation... on the Quotation, click on PayDate and hit the delete key. You can customize these all you want! You can do the same with other ORMs, just takes a little more work. With NHibernate you would manually create the Models, then map them to the same table, but only map what you need.

Entity Framework 4 Repository returning IList: What C# code could limit which POCO fields populate?

If you populate a drop down list of possible values, you only want the database query to pull two fields, a value and text (like customer ID and Name).
However, your Repository returns POCOs, namely the entire Customer record.
I wouldn't think you should create a POCO for every single DDL list you need, so how does one specify to a repository what fields to populate using Entity Framework 4, ASP.NET POCO generator, and a repository that doesn't return IQueryable or IEnumerable (doesn't defer the SQL call when leaving the repository)?
Simply put, how do you inform the repository to only populate some fields of your POCO?
I bet you could use an internal class to pull out different content, then AutoMap them to your Domain Models before you leave the Repository. It would mean duplicating classes though.
Otherwise you could return IQueryable from your Repository, which has all kinds of problems, like querying a set of data when you .Count then again when you use the data.

Is it good to use a static EF object context in an MVC application for better perf?

Let's start with this basic scenario:
I have a bunch of Tables that are essentially rarely changed Enums (e.g. GeoLocations, Category, etc.) I want to load these into my EF ObjectContext so that I can assign them to entities that reference them as FK. These objects are also used to populate all sorts of dropdown controls. Pretty standard scenarios so far.
Since a new controller is created for each page request in MVC, a new entity context is created and these "enum" objects are loaded repeatedly. I thought about using a static context object across all instances of controllers (or repository object).
But will this require too much locking and therefore actually worsen perf?
Alternatively, I'm thinking of using a static context only for read-only tables. But since entities that reference them must be in the same context anyway, this isn't any different from the above.
I also don't want to get into the business of attaching/detaching these enum objects. Since I believe once I attach a static enum object to an entity, I can't attach it again to another entity??
Please help, I'm quite new to EF + MVC, so am wondering what is the best approach.
Personally, I never have any static Context stuff, etc. For me, when i call the database (CRUD) I use that context for that single transaction/unit of work.
So in this case, what you're suggesting is that you wish to retrieve some data from the databse .. and this data is .. more or less .. read only and doesn't change / static.
Lookup data is a great example of this.
So your Categories never change. Your GeoLocations never change, also.
I would not worry about this concept on the database/persistence level, but on the application level. So, just forget that this data is static/readonly etc.. and just get it. Then, when you're in your application (ie. ASP.NET web MVC controller method or in the global.asax code) THEN you should cache this ... on the UI layer.
If you're doing a nice n-tiered MVC app, which contains
UI layer
Services / Business Logic Layer
Persistence / Database data layer
Then I would cache this in the Middle Tier .. which is called by the UI Layer (ie. the MVC Controller Action .. eg. public void Index())
I think it's important to know how to seperate your concerns .. and the database stuff is should just be that -> CRUD'ish stuff and some unique stored procs when required. Don't worry about caching data, etc. Keep this layer as light as possible and as simple as possible.
Then, your middle Tier (if it exists) or your top tier should worry about what to do with this data -> in this case, cache it because it's very static.
I've implemented something similar using Linq2SQL by retrieving these 'lookup tables' as lists on app startup and storing them in ASP's caching mechanism. By using the ASP cache, I don't have to worry about threading/locking etc. Not sure why you'd need to attach them to a context, something like that could easily be retrieved if necessary via the table PK id.
I believe this is as much a question of what to cache as how. When your are dealing with EF, you can quickly run into problems when you try to persist EF objects across different contexts and attempt to detach/attach those objects. If you are using your own POCO objects with custom t4 templates then this isn't an issue, but if you are using vanilla EF then you will want to create POCO objects for your cache.
For most simple lookup items (i.e numeric primary key and string text description), you can use Dictionary. If you have multiple fields you need to pass and back with the UI then you can build a more complete object model. Since these will be POCO objects they can then be persisted pretty much anywhere and any way you like. I recommend using caching logic outside of your MVC application such that you can easily mock the caching activity for testing. If you have multiple lists you need to cache, you can put them all in one container class that looks something like this:
public class MyCacheContainer
{
public Dictionary<int, string> GeoLocations { get; set; }
public List<Category> Categories { get; set; }
}
The next question is do you really need these objects in your entity model at all. Chances are all you really need are the primary keys (i.e. you create a dropdown list using the keys and values from the dictionary and just post the ID). Therefore you could potentially handle all of the lookups to the textual description in the construction of your view models. That could look something like this:
MyEntityObject item = Context.MyEntityObjects.FirstOrDefault(i => i.Id == id);
MyCacheContainer cache = CacheFactory.GetCache();
MyViewModel model = new MyViewModel { Item = item, GeoLocationDescription = GeoLocations[item.GeoLocationId] };
If you absolutely must have those objects in your context (i.e. if there are referential entities that tie 2 or more other tables together), you can pass that cache container into your data access layer so it can do the proper lookups.
As for assigning "valid" entities, in .Net 4 you can just set the foreign key properties and don't have to actually attach an object (technically you can do this in 3.5, but it requires magic strings to set the keys). If you are using 3.5, you might just try something like this:
myItem.Category = Context.Categories.FirstOrDefault(c => c.id == id);
While this isn't the most elegant solution and does require an extra roundtrip to the DB to get a category you don't really need, it works. Doing a single record lookup based on a primary key should not really be that big of a hit especially if the table is small like the type of lookup data you are talking about.
If you are stuck with 3.5 and don't want to make that extra round trip and you want to go the magic string route, just make sure you use some type of static resource and/or code generator for your magic strings so you don't fat finger them. There are many examples here that show how do assign a new EntityKey to a reference without going to the DB so I won't go into that on this question.

MVC Model: submitting multiple objects to the View

I'm not sure if there is a difference in these two methods. If so, which would be considered the better practice when submitting more than one object to the View.
Having the controller make separate calls to the datalayer for each object model and then wrapping the objects in a model to send to view.
Defining a "presentation" model and having the controller call that single model to send to the view.
other...?
I'm assuming here that you have a view that presents some information from more than one model, perhaps in a list format. For example, you may have a model of a customer which has a set of contacts, but in your list you want to choose to show some of the customer details along with the name and phone number of the primary contact. What I would typically do in a situation like this is define a specific "presentation" model that consists of just those details that I may want to show in this combined view. It would typically be a read-only model. Using LINQ to SQL I might even define this as a table-valued function (to support search) and associate it with a view that encapsulates the join of the various tables. With both you can add the view-based "presentation" model to your DBML and associate the table-valued function with it as a method on the data context.
I prefer doing this because I believe that it is more efficient in terms of queries to construct the query on the server and simply use it from the code. If you weren't using the table-valued function for searching, you might be able to construct the query in code and select into a "presentation" class. I would favor an actual class over an anonymous type for ease of use in the view. Getting the properties from an anonymous type in the view would be difficult.
You should send to the View a single object, sometimes termed a ViewModel object, containing all the data (including domain model objects) that the view will need.

Resources