Page loading is slow in MVC Application - asp.net-mvc

I have developed application in MVC using rojar view.it working fine but one of testing server rander the page in 4 seconds and on production server it takes 30-35 seconds.
Database on both the server are different nut code and number of records are same on both the server
foreach (var subcategpory in Model.category.RFP_SubCategories)
{
if (subcategpory.RFP_Questions.Any(q => q.SubCategoryId == subcategpory.SubCategoryId))
{
<div class="vendor-block">
<div class="vendor-title border-bottom">
<h6>#subcategpory.SubCategory</h6>
<p>Selected:<span class="selectedQuestion" id="selectedQuestion_#subcategpory.SubCategoryId">0</span></p>
</div>
<ul class="vendor-list">
#if (Model.category.RFP_Questions != null)
{
foreach (var que in subcategpory.RFP_Questions.Where(q => q.SubCategoryId == subcategpory.SubCategoryId))
{
bool IsChecked = Model.category.RFP_SelectedQuestions.Any(sq => sq.QuestionId == que.QuestionId);
}
}
</ul>
</div>
}
}
Can you please suggest any way to resolve the issue and actual reason.
Thanks,
Vishal

I would check that you have the same indexes on both databases as possibly there has been an index created on the test server which is missing on the live one.
Another obvious point would be that the live server may have more resource contention due to other things accessing the server. This situation could also be remedied by having correct indexes allowing the query to complete quickly.
I would check the SubCategoryId and QuestionId fields have appropriate indexes.
You could also look at the statistics and ensure they are up-to-date on the live server. This: https://msdn.microsoft.com/en-us/library/ms173804.aspx may be worth looking at.

You can avoid deferred execution. Try this:
Don't use Model.category.RFP_SubCategories directly.Instead:
var lst=Model.category.RFP_SubCategories.ToList()
and loop through using lst
You can also change
foreach (var que in subcategpory.RFP_Questions.Where(q => q.SubCategoryId == subcategpory.SubCategoryId))
{
bool IsChecked = Model.category.RFP_SelectedQuestions.Any(sq => sq.QuestionId == que.QuestionId);
}
to
var qstnsList= subcategpory.RFP_Questions.Where(q => q.SubCategoryId == subcategpory.SubCategoryId).ToList()
and use qstnsList in foreach loop if data exist.
Try this and do tell me if it saved time or not.

Related

Observed Lists and Maps, and Firebase, oh my. How can I improve this mess?

So this is what I ended up with to get realtime starring/liking (of communities, in my case) working, with a Firebase datastore. It's a mess and surely I'm missing some fundamentals.
Here my element gets communities, each as a Map community stored in an observed List communities. It has to rewrite that List several times as it changes each community Map based on the results of the changed star count and the user's starred state, and some other fun:
getCommunities() {
// Since we call this method a second time after user
// signed in, clear the communities list before we recreate it.
if (communities.length > 0) { communities.clear(); }
var firebaseRoot = new db.Firebase(firebaseLocation);
var communityRef = firebaseRoot.child('/communities');
// TODO: Undo the limit of 20; https://github.com/firebase/firebase-dart/issues/8
communityRef.limit(20).onChildAdded.listen((e) {
var community = e.snapshot.val();
// snapshot.name is Firebase's ID, i.e. "the name of the Firebase location",
// so we'll add that to our local item list.
community['id'] = e.snapshot.name();
print(community['id']);
// If the user is signed in, see if they've starred this community.
if (app.user != null) {
firebaseRoot.child('/users/' + app.user.username + '/communities/' + community['id']).onValue.listen((e) {
if (e.snapshot.val() == null) {
community['userStarred'] = false;
// TODO: Add community star_count?!
} else {
community['userStarred'] = true;
}
print("${community['userStarred']}, star count: ${community['star_count']}");
// Replace the community in the observed list w/ our updated copy.
communities
..removeWhere((oldItem) => oldItem['alias'] == community['alias'])
..add(community)
..sort((m1, m2) => m1["updatedDate"].compareTo(m2["updatedDate"]));
communities = toObservable(communities.reversed.toList());
});
}
// If no updated date, use the created date.
if (community['updatedDate'] == null) {
community['updatedDate'] = community['createdDate'];
}
// Handle the case where no star count yet.
if (community['star_count'] == null) {
community['star_count'] = 0;
}
// The live-date-time element needs parsed dates.
community['updatedDate'] = DateTime.parse(community['updatedDate']);
community['createdDate'] = DateTime.parse(community['createdDate']);
// Listen for realtime changes to the star count.
communityRef.child(community['alias'] + '/star_count').onValue.listen((e) {
int newCount = e.snapshot.val();
community['star_count'] = newCount;
// Replace the community in the observed list w/ our updated copy.
// TODO: Re-writing the list each time is ridiculous!
communities
..removeWhere((oldItem) => oldItem['alias'] == community['alias'])
..add(community)
..sort((m1, m2) => m1["updatedDate"].compareTo(m2["updatedDate"]));
communities = toObservable(communities.reversed.toList());
});
// Insert each new community into the list.
communities.add(community);
// Sort the list by the item's updatedDate, then reverse it.
communities.sort((m1, m2) => m1["updatedDate"].compareTo(m2["updatedDate"]));
communities = toObservable(communities.reversed.toList());
});
}
Here we toggle the star, which again replaces the observed communities List a few times as we update the count in the affected community Maps and thus rewrite the List to reflect that:
toggleStar(Event e, var detail, Element target) {
// Don't fire the core-item's on-click, just the icon's.
e.stopPropagation();
if (app.user == null) {
app.showMessage("Kindly sign in first.", "important");
return;
}
bool isStarred = (target.classes.contains("selected"));
var community = communities.firstWhere((i) => i['id'] == target.dataset['id']);
var firebaseRoot = new db.Firebase(firebaseLocation);
var starredCommunityRef = firebaseRoot.child('/users/' + app.user.username + '/communities/' + community['id']);
var communityRef = firebaseRoot.child('/communities/' + community['id']);
if (isStarred) {
// If it's starred, time to unstar it.
community['userStarred'] = false;
starredCommunityRef.remove();
// Update the star count.
communityRef.child('/star_count').transaction((currentCount) {
if (currentCount == null || currentCount == 0) {
community['star_count'] = 0;
return 0;
} else {
community['star_count'] = currentCount - 1;
return currentCount - 1;
}
});
// Update the list of users who starred.
communityRef.child('/star_users/' + app.user.username).remove();
} else {
// If it's not starred, time to star it.
community['userStarred'] = true;
starredCommunityRef.set(true);
// Update the star count.
communityRef.child('/star_count').transaction((currentCount) {
if (currentCount == null || currentCount == 0) {
community['star_count'] = 1;
return 1;
} else {
community['star_count'] = currentCount + 1;
return currentCount + 1;
}
});
// Update the list of users who starred.
communityRef.child('/star_users/' + app.user.username).set(true);
}
// Replace the community in the observed list w/ our updated copy.
communities.removeWhere((oldItem) => oldItem['alias'] == community['alias']);
communities.add(community);
communities.sort((m1, m2) => m1["updatedDate"].compareTo(m2["updatedDate"]));
communities = toObservable(communities.reversed.toList());
print(communities);
}
There's also some other craziness where we have to get the list of communities again when app.changes because we only load app.user after the app and list initially load, and now that we have the user we need to turn on the appropriate stars. So my attached() looks like:
attached() {
app.pageTitle = "Communities";
getCommunities();
app.changes.listen((List<ChangeRecord> records) {
if (app.user != null) {
getCommunities();
}
});
}
There, it seems I could just be getting the stars and updating said each affected community Map, then repopulating the observed communities List, but that's the least of it.
The full thing: https://gist.github.com/DaveNotik/5ccdc9e74429cf87d641
How can I improve all this Map/List management, e.g. where every time I change a community Map, I have to rewrite the whole communities List? Should I be thinking of it differently?
What about all this querying Firebase? Surely, there's a better way, but it seems I need to do a lot to keep it realtime, and also the element gets attached and detached, so it seems I need to run getCommunities() each time. Unless the OOP way is objects get created, and they're always there to be observed whenever the element is attached? I'm missing those fundamentals.
This app.changes business to handle the case where we load the list before we have the app.user (which then means we want to load her stars) - is there a better way?
Other ridiculousness?
Big question, I know. Thank you for helping me get a handle on the right approach as I move forward!
I think there is two different ways to choose, if you want to keep a data of your application in real time sync with server database:
1 Polling (pull method ie. a client pulls the data from server)
Application polls ie. requests the updated data from the server. Polling can be automatic (for example with interval of 60s) or requested by user (= refresh). The short automatic interval will cause high load on server and with long interval you lose real time feeling.
2 Full-duplex (push method ie. server can push the data to the client)
An application and a server have full-duplex connection in between and server is able to send the data or a notification of the data available to the client. Then the client can decide whether or not to retrieve the data.
This method is a modern one, because it'll keep the net traffic and the server load in minimum and yet providing a real time updates.
The firebase boasts with this kind of updates, but I'm not sure is it full-dublex or just a clever way of polling. Websocket protocol is a real full-duplex connection and dart server supports it.
The updated data from a server can include:
1 A full dataset
Basically the server sends a full dataset (=initial query) and the server doesn't "know" anything about updated data. This is easiest way to go, if you have reasonable small datasets. Many times you'll have a very small datasets among the big ones, so this way can be useful.
2 A dataset including a new data only
The server can send a dataset based on modified timestamp ie. every time a record in the database changes, a timestamp for update will be saved and the query can be filtered based on this timestamp. In other words application knows when it has last updated the data and then requests newer data.
3 A changed record
A server keeps a track of updated data and sends it to the application. The data can be sent record by record when changes occurs or server can collect the data for a bigger chunks to be sent. This method requires a server to keep a track of every client connected in order to send a correct data to each client. When you add an authentication process for clients ie. not every data can be send to all, it can get quite complicated.
I think the easiest way is to use the method number 2 for updated data.
Last thing...
What to do with the data received?
1 Handle everything as a new
If application receives an updated data, it will destroy/clear all the lists and maps and recreate/refill them with the new data. Typical problems with this are a user loses a current position on a page or the data user were looking jumps around. If application has modified or extended an old data for some reason, all those modifications will be lost. This method works ok, if a user requests a refresh.
2 Update only the changed data
The application never clears initial list or maps, it just updates them with a new received data. Typically you will construct a new combined map from queried data for your specific need (for example a certain view). The combined map has already all information you want to show in the specific view (default values even if the initial queries didn't had the data for the field) and you just update a new values in it.
If the updated information needs a new member in the list you just add it in the end.
If the updated information requires a deletion from the list, it might be a good thing to use extra field "active" and filter the list/map with it. With filtering you won't lose any referencies or so.
If you need to sort a data or filter it, it should be done by a view or user request. Basically the data is stored in the application and updated as needed. When a user needs to see the data in a specific way, the view should show the data a proper way. This is called model-controller-view and the main idea is to separate the data from the view.
I'm sorry this long answer didn't answer any of your questions, but I tried to cut this challenge to a smaller chunks. Many times you can see an interface between these chunks and you can design and organize your code nicely by using these interfaces.

MultiTenancy Orchard - How to find out which tenant the request is coming from

I have searched for quite a while, but I have not found any thread explaining how exactly to find out which Tenant is the current one in code. For example, I want to change some logic based off of what Tenant is active like so:
IQueryable<ContentPartRecord> getContentPartDates;
if (Tenat == ExampleTenant)
{
getContentPartDates = GetContentPartDates((int)Id)
.Where(ss => ss.SalesStatus == "Guaranteed")
.OrderBy(x => x.start_date);
}else {
getContentPartDates = GetContentPartDates((int) Id).OrderBy(x => x.start_date);
}
What exactly is the best way to do this?
Thanks in advance.
Inject ShellSettings in ctor. This object contains all data (from Settings.txt file) about the shell (ie. tenant) in which current unit of work executes.

Perfomance issue - .Count in MVC view

For several pages I use a .Count inside a foreach loop
#model ICollection<Item>
foreach(var item in Model)
{
#item.Flight.FlightReservations.count
}
Because of lazy loading the EF makes a round trip to the database for this.
Now I want to fix this by using this or linq version:
Include("List.Flight.FlightReservations")
Doing this makes loading my dbSet take even longer than those foreach round trips
How can I 'load' parts of only 1 object?
I would like to use context.Items.Single(p => p.id == id).Include(.....)
So I only load 1 item fully.
Or any other solutions for this?
(A way to force load item.List.item2.List inside controller)
Any suggestions are welcome :) Thanks
EDIT : now using
Where(..).ToDictionary(item => item, item => item.Flight.FlightReservations.Count);
Also noticed adding an index to my 'clustered index' table helped a little.
Still slow though
var f = _pr.FindBy(duifid);
var result = (from p in f.IngeschrevenVluchten
select new PrestatieModel
{
Eindpos = p.Eindpositie,
Locatie = p.Vlucht.Locatie.Naam,
AantalInschrijvingen = p.Vlucht.Inschrijvingen.Count(),
Vlucht = p.Vlucht
});
This query executes very fast, making a IEnumerable<Model>. But still it loads very slow once sent to the view.
return PartialView(result);

Enumerating Documents in Umbraco

I'm working on some C# code that performs tasks based on certain documents. Currently, I'm using Document[] releaseDocs = Document.GetRootDocuments() and then looping through the results.
Is it possible to do something like Document[] releaseDocs = Document.GetRootDocuments().Where(m => m.Published == false); where I could take advantage of the API to only get Published Documents and Documents with certain set Variables? If so, how, because that method doesn't appear to work.
Try something like this:
Document[] documents = Document.GetRootDocuments();
foreach (var doc in documents)
{
// Do Something
}
This should work just fine:
Document[] releaseDocs = Document.GetRootDocuments().Where(m =>
m.Published == false &&
m.getProperty("SomeAlias").Value.Equals("Some Value")).ToArray();

ADO.Net Entity Framework/Linq

I'm look at learning a bit more ASP.Net MVC and Linq To Entity.
I'm working on a project using this and am having a problem with the following line of code
ViewData["ProjectName"] = db.Projects.FirstOrDefault(p => p.ProjectId == task.ProjectId).ProjectName;
It works fine when the record exists but if no record exist it errors because I am trying to examine the ProjectName property of a null object. I realise I could cast the object to a variable and test if its null before storing the ProjectName into the ViewData but am just wondering if there is a neater way of doing this?
I know its a simple question and I could just work around it but if there is a better way of doing this it would be good to know.
Thanks
Gavin
var project = db.Projects.FirstOrDefault(p => p.ProjectId == task.ProjectId);
if (project != null)
{
ViewData["ProjectName"] = project.ProjectName;
}
else
{
//........
}
No cast needed.
Or skip the condition altogether and do this:
ViewData["ProjectName"] = db.Projects.Where(p => p.ProjectId == task.ProjectId)
.Select(p => p.ProjectName).FirstOrDefault();

Resources