DataTables Asp.Net MVC 4 Process - ajax

I have a project which using DataTables. Its working as ajax request. Its completing in 8-12 seconds. I need to optimize this code but i don't know how. String Process is worst part.
public JsonResult PageModel(Models.DataTable.ParamModel model, byte type)
{
DateTime startTime = DateTime.Now;
using (var db = Helper.Context())
{
var allEntries = db.MembershipVacations.Where(i => i.Type == type).ToList();
IEnumerable<DatabaseProcedure.Models.MembershipVacation> list = new List<DatabaseProcedure.Models.MembershipVacation>();
Func<DbModels.MembershipVacation, string> orderingFunction = (c =>
model.iSortCol_0 == 0 ? c.Membership.Username : "");
Func<DbModels.MembershipVacation, DateTime> dateOrderingFunction = (c =>
model.iSortCol_0 == 1 ? c.PostDate :
model.iSortCol_0 == 3 ? c.StartDate :
model.iSortCol_0 == 4 ? c.EndDate : DateTime.MaxValue);
/*Func<DbModels.MembershipVacation, string> orderingFunction = (c => model.iSortCol_0 == 1 ? c.ID.ToString() :
model.iSortCol_0 == 2 ? c.Membership.Username :
c.Description);*/
if (User.IsInRole("Admin"))
{
if (model.sSearch.IsNull())
{
if (model.sSortDir_0 == "asc")
{
list = allEntries
.OrderBy(orderingFunction);
if (model.iSortCol_0 == 1 || model.iSortCol_0 == 3 || model.iSortCol_0 == 4)
{
list = allEntries.OrderBy(dateOrderingFunction);
}
}
else
{
list = allEntries
.OrderByDescending(orderingFunction);
if (model.iSortCol_0 == 1 || model.iSortCol_0 == 3 || model.iSortCol_0 == 4)
{
list = allEntries.OrderByDescending(dateOrderingFunction);
}
}
list = list
.Skip(model.iDisplayStart)
.Take(model.iDisplayLength);
}
else
{
list = allEntries
.Where(i =>
i.Membership != null ? i.Membership.Username.Contains(model.sSearch, StringComparison.OrdinalIgnoreCase) : false
|| i.Membership != null && i.Membership.Department != null ? i.Membership.Department.Name.Contains(model.sSearch, StringComparison.OrdinalIgnoreCase) : false
|| i.StartDate.ToString().Contains(model.sSearch, StringComparison.OrdinalIgnoreCase)
|| i.EndDate.ToString().Contains(model.sSearch, StringComparison.OrdinalIgnoreCase));
if (model.sSortDir_0 == "asc")
{
list = list
.OrderBy(orderingFunction);
if (model.iSortCol_0 == 1 || model.iSortCol_0 == 3 || model.iSortCol_0 == 4)
{
list = list.OrderBy(dateOrderingFunction);
}
}
else
{
list = list
.OrderByDescending(orderingFunction);
if (model.iSortCol_0 == 1 || model.iSortCol_0 == 3 || model.iSortCol_0 == 4)
{
list = list.OrderByDescending(dateOrderingFunction);
}
}
}
}
else
{
var approveList = db.MembershipVacationApproves.ToList();
if (model.sSearch.IsNull())
{
list = approveList
.Where(i => i.MembershipID == UI.Helper.User.ID || i.MembershipVacation.MembershipID == UI.Helper.User.ID)
.Select(i => i.MembershipVacation)
.Distinct()
.Where(i => i.Type == type)
.Skip(model.iDisplayStart)
.Take(model.iDisplayLength);
}
else
{
list = approveList
.Where(i => i.MembershipID == UI.Helper.User.ID || i.MembershipVacation.MembershipID == UI.Helper.User.ID)
.Select(i => i.MembershipVacation)
.Distinct()
.Where(i =>
i.Type == type && (
i.Membership != null ? i.Membership.Username.Contains(model.sSearch, StringComparison.OrdinalIgnoreCase) : false
|| i.Membership.Department != null ? i.Membership.Department.Name.Contains(model.sSearch, StringComparison.OrdinalIgnoreCase) : false
|| i.StartDate.ToString().Contains(model.sSearch, StringComparison.OrdinalIgnoreCase)
|| i.EndDate.ToString().Contains(model.sSearch, StringComparison.OrdinalIgnoreCase)))
.Skip(model.iDisplayStart)
.Take(model.iDisplayLength);
}
}
List<string[]> result = new List<string[]>();
foreach (var item in list)
{
var waiting = item.MembershipVacationApproves.Count(i => i.State == UI.Vacation.ApproveState.Waiting) > 0;
var cancel = item.MembershipVacationApproves.Count(i => i.State == UI.Vacation.ApproveState.Cancel) > 0;
var approve = item.MembershipVacationApproves.Count(i => i.State == UI.Vacation.ApproveState.Approve) == item.MembershipVacationApproves.Count;
var edit = item.Membership.MembershipRelation != null ? item.Membership.MembershipRelation.OwnerID == UI.Helper.User.ID : false;
var canApprove = item.MembershipVacationApproves.Count(i => i.MembershipID == UI.Helper.User.ID) == 1;
StringBuilder name_link = new StringBuilder(),
durumu = new StringBuilder(),
islemler = new StringBuilder();
if (item.Membership.Staff != null)
{
name_link.Append("" + item.Membership.Username + "");
}
else
{
name_link.Append(item.Membership.Username);
}
if (!cancel)
{
if (approve)
{
if (DateTime.Now < item.StartDate)
{
durumu.Append("<small class='btn green-bg'>İstek onayladı.</small>");
}
else
{
if (DateTime.Now > item.EndDate)
{
durumu.Append("<small class='btn green'>Kişi izinden dönmüş.</small>");
}
else
{
durumu.Append("<small class='btn green'>Kişi izinde.</small>");
}
}
}
else
{
durumu.Append("<small class='btn orange'>İstek onaylanması için bekleniyor.</small>");
}
}
else
{
durumu.Append("<small class='btn red'>İstek iptal edilmiş</small>");
}
islemler.Append("<div class='btn-group'>");
islemler.Append("<a class='btn green' href='#' data-toggle='dropdown'><i class='icon-user'></i>İşlemler");
islemler.Append("<i class='icon-angle-down'></i></a>");
islemler.Append("<ul class='dropdown-menu'>");
islemler.Append("<li><a href='" + this.Url.Action("RequestDetail", "Vacation", new { id = item.ID }) + "' data-toggle='modal' data-target='#'><i class='icon-search'>");
islemler.Append("</i>İncele</a></li>");
/*if (User.IsInRole("İzin Onaylama") || edit)
{
islemler += "<li><a href='" + this.Url.Action("Request", "Vacation", new { id = item.ID }) + "'><i class='icon-search'>";
islemler += "</i>Düzenle</a></li>";
}*/
if (!(DateTime.Now > item.StartDate && approve) && canApprove)
{
islemler.Append("<li><i class='icon-ok'></i>Onayla</li>");
islemler.Append("<li><a href=" + this.Url.Action("DeclinePage", "Vacation", new { id = item.ID }) + " data-toggle='modal' data-target='#'><i class='icon-remove'></i>Onaylama</a></li>");
}
islemler.Append("</ul>");
islemler.Append("</div>");
result.Add(
new string[]
{
name_link.ToString(),
item.PostDate.ToString(),
item.Membership.Department != null ? item.Membership.Department.Name : string.Empty,
item.StartDate.ToString(),
item.EndDate.ToString(),
durumu.ToString(),
islemler.ToString()
});
}
var total = (DateTime.Now - startTime);
System.Diagnostics.Debug.WriteLine("total ms " + total.TotalMilliseconds);
return Json(new
{
sEcho = model.sEcho,
iTotalRecords = allEntries.Count(),
iTotalDisplayRecords = allEntries.Count(),
aaData = result
}, JsonRequestBehavior.AllowGet);
}
}
Worst part is last foreach process for make buttons and permissions

I would guess that you have an N+1 SQL query issue in your last foreach loop: you build list then trigger 5 SQL queries for each item in the list.
Advice to diagnose and fix:
Install MiniProfiler and enable database
profiling - then you'll be able to see which SQL queries are being
triggered by the request, and if you have any duplicate queries.
Make use of EntityFramework's Include method, to eager load related data when you're querying the items for list. This will save EF from having to issue separate duplicate queries within your foreach.

Related

How to fix the wait operation is timed out? Works some time but is not working finely

I m a learner of MVC and has very limited knowledge. This is working but too slow.
Here are my few questions.
1.Does using the controller instead of the API degrade the performance?
2.Are there any cons to implementing an individual search for each column?
3.What is bad practice in this code? How can I correct them?
4.Table compounds have more than 200k rows. how can I make it as fast as possible with Ajaxified search, sortable, individual search for each column and pagination?
[OutputCache(Duration = 10, VaryByParam = "none")]
public ActionResult AjaxCompound(JQueryDataTableParamModel param)
{
IQueryable<Compound> allCompounds = _context.Compounds.Include(p => p.Oil);
IEnumerable<Compound> filteredCompounds;
if (!string.IsNullOrEmpty(param.sSearch))
{
filteredCompounds = allCompounds
.Where(c => c.Oil.CommonName.Contains(param.sSearch)
//||
//c.Oil.BotanicalName.Contains(param.sSearch)
||
c.Name.Contains(param.sSearch)
||
c.RI.Contains(param.sSearch)
||
c.MolecularWeight.Contains(param.sSearch)
||
c.MolecularFormula.Contains(param.sSearch)
||
c.AreaPercent.Contains(param.sSearch)
);
}
else
{
filteredCompounds = allCompounds;
}
var sortColumnIndex = Convert.ToInt32(Request["iSortCol_0"]);
Func<Compound, string> orderingFunction = (c => sortColumnIndex == 1 ? c.Oil.CommonName :
//sortColumnIndex == 2 ? c.Oil.BotanicalName :
sortColumnIndex == 2 ? c.Name :
sortColumnIndex == 3 ? c.RI :
sortColumnIndex == 4 ? c.MolecularFormula :
sortColumnIndex == 5 ? c.MolecularWeight :
c.AreaPercent);
var commonFilter = Convert.ToString(Request["sSearch_1"]);
//var botanicalFilter = Convert.ToString(Request["sSearch_2"]);
var name = Convert.ToString(Request["sSearch_2"]);
var rI = Convert.ToString(Request["sSearch_3"]);
var mW = Convert.ToString(Request["sSearch_4"]);
var mF = Convert.ToString(Request["sSearch_5"]);
var areaPercent = Convert.ToString(Request["sSearch_6"]);
if (!string.IsNullOrEmpty(commonFilter))
{
filteredCompounds = filteredCompounds.Where(c => c.Oil.CommonName.Contains(commonFilter));
}
//if (!string.IsNullOrEmpty(botanicalFilter))
//{
// filteredCompounds = filteredCompounds.Where(c => c.Oil.BotanicalName.Contains(botanicalFilter));
//}
if (!string.IsNullOrEmpty(name))
{
filteredCompounds = filteredCompounds.Where(c => c.Name.Contains(name));
}
if (!string.IsNullOrEmpty(rI))
{
filteredCompounds = filteredCompounds.Where(c => c.RI.Contains(rI));
}
if (!string.IsNullOrEmpty(mF))
{
filteredCompounds = filteredCompounds.Where(c => c.MolecularFormula.Contains(mF));
}
if (!string.IsNullOrEmpty(mW))
{
filteredCompounds = filteredCompounds.Where(c => c.MolecularWeight.Contains(mW));
}
if (!string.IsNullOrEmpty(areaPercent))
{
filteredCompounds = filteredCompounds.Where(c => c.AreaPercent.Contains(areaPercent));
}
var sortDirection = Request["sSortDir_0"];
if (sortDirection == "asc")
filteredCompounds = filteredCompounds.OrderBy(orderingFunction);
else
filteredCompounds = filteredCompounds.OrderByDescending(orderingFunction);
var displayedCompounds = filteredCompounds
.Skip(param.iDisplayStart)
.Take(param.iDisplayLength);
var result = from c in displayedCompounds
select new[] { Convert.ToString(c.PaperId), c.Oil.CommonName, /*c.Oil.BotanicalName,*/ c.Name, c.RI, c.MolecularWeight, c.MolecularFormula, c.AreaPercent };
return Json(new
{
sEcho = param.sEcho,
iTotalRecords = allCompounds.Count(),
iTotalDisplayRecords = filteredCompounds.Count(),
aaData = result
},
JsonRequestBehavior.AllowGet);
}

Kendo Grid Columns Display ActionLink

I have a Kendo grid with multiple columns, but I want to display the Name of the Doc and when I click it to get the path of that Doc.
View
columns.Bound(od => od.DocumentListName).Width(150).ClientTemplate("#=generateTemplate(DocumentListName)#");
JavaScript function that displays the list of Docs
function generateTemplate(DocumentList) {
var template = "<ul>"
if (DocumentList == null || DocumentList == undefined) {
template = template + "<li>N/A</li>";
} else {
for (var i = 0; i < DocumentList.length; i++) {
template = template + "<li>" + DocumentList[i] + "</li>";
}
}
return template + "</ul>";
}
And my ActionResult
public ActionResult GetDocuments(ViewModel VM)
{
using (var db = new DB())
{
var docName = db.Documents.Include("Doc").Where(x => x.Id == VM.Id).Select(z => z.Name).ToList();
if (docName.Count() != 0) {
}
Vm.DocumentListName = docName;
var docPath = db.Documents.Include("Doc").Where(x => x.Id == Vm.Id).Select(z => z.Path).ToList();
VM.DocumentPathList = docPath;
return Json(VM, JsonRequestBehavior.AllowGet);
}
}
I know I can display the Path as ActionLink this way
columns.Template(#<text>#Html.ActionLink(#item.DocumentPathList.ToString(), "GetDocuments", "Controller") </text>).ClientTemplate("<a href='#=DocumentPathList#</a>").Title("Docs");
But how can I combine them?
function generateTemplate(DocumentList) {
var template = "<ul>";
if (DocumentList == null || DocumentList == undefined) {
template = template + "<li> </li>";
} else {
for (var i = 0; i < DocumentList.length; i++) {
var url = '#Url.Action("DownloadDocument", "Controller")?filename=' + DocumentListName[i];
template = template + "<a href='" + url + "'>" + DocumentList[i] + "</a> ";
}
}
return template + "</ul>";
}

how to get count new message found as per enquiry/ticket with two way conditions

i 'm working with crm application. i developed it finally i'm getting confused how i detect new messages as per flag must have display and message not have to true.
here is my db schema for understanding problem.
here is my constructed query to get new message count :
int new_messages = 0;
foreach (var enquiry in db.Enquiries.Where(i => (i.ForwardTo.Equals(userid) || i.AttendBy.Equals(userid))).ToList())
{
if (enquiry != null)
{
bool IsIns = true;
foreach (var flag in db.Flags.Where(f => f.Enquiry_History_id.Equals(enquiry.Ref_no) && f.User_id.Equals(userid)).Select(f => new { IsDisplay = f.IsDisplay }).ToList())
{
if (flag != null)
{
if (flag.IsDisplay == false)
{
IsIns = false;
}
}
}
if (IsIns == true)
{
foreach (var message in db.Messages.Where(m => m.Enquiry_History_id.Equals(enquiry.Ref_no) && m.User_id.Equals(userid)).Select(m => new { IsRead = m.IsRead }).ToList())
{
if (message.IsRead == true)
{
//do another stuff
}
else
{
new_messages++;
}
}
}
}
}
lbl_msg.Text = new_messages.ToString();
here i have to take each enquiry that have been AttendBy or ForwardBy to user and check it first it should be display is not false and after that check as per each message should not have IsRead to true. i'm trying with my best way but this not gives me out put as i want.
i have an idea just insert two values one for true which generate message and second for false to froward. and at finding out only which have IsRead to false.
something like this way :
using (DataClassesDataContext db = new DataClassesDataContext())
{
string userid = db.Users.Where(u => u.Username.Equals((String)Session["Username"])).Select(u => u.Ref_no).SingleOrDefault().ToString();
bool IsIns = true;
foreach (var enquiry in db.Enquiries.Where(i => i.AttendBy.Equals(userid) || i.ForwardTo.Equals(userid)).ToList())
{
if (enquiry != null)
{
foreach (var flag in db.Flags.Where(f => f.Enquiry_History_id.Equals(enquiry.Ref_no) && f.User_id.Equals(userid)).Select(f => new { IsDisplay = f.IsDisplay }).ToList())
{
if (flag.IsDisplay == false)
{
IsIns = false;
}
if (IsIns == true)
{
foreach (var message in db.Messages.Where(m => m.Enquiry_History_id.Equals(enquiry.Ref_no)).ToList())
{
if (message != null)
{
bool IsIns1 = false;
foreach (var messageflag in db.MessageFlags.Where(mf => mf.MessageId.Equals(message.Id) && mf.UserId.Equals(userid)).Select(mf => new
{
IsRead = mf.IsRead,
User_id = mf.UserId,
Message = message.body,
CreatedDate = message.Created_date
}).ToList())
{
if (messageflag.IsRead == false)
{
IsIns1 = true;
}
if (IsIns1 == true)
{
DataRow dr = dt.NewRow();
dr["Ref_no"] = enquiry.Ref_no.ToString();
dr["Name"] = db.Users.Where(u => u.Ref_no.Equals(messageflag.User_id)).Select(u => u.FirstName + ' ' + u.LastName).SingleOrDefault().ToString();
dr["UserId"] = db.Users.Where(u => u.Ref_no.Equals(messageflag.User_id)).Select(u => u.Ref_no).SingleOrDefault().ToString();
dr["Message"] = messageflag.Message.ToString();
dr["CreatedDate"] = messageflag.CreatedDate.ToString();
dt.Rows.Add(dr);
}
}
}
}
}
}
}
}
myDataSet.Tables.Add(dt);
lbl_count_messages.Text = myDataSet.Tables[0].Rows.Count.ToString();
if (myDataSet.Tables[0].Rows.Count == 0)
{
message_alert.Visible = false;
}
Repeater_Messages.DataSource = myDataSet;
Repeater_Messages.DataBind();
}

IQueryable Sort not working

What is wrong with the code below with regards to sorting? The sort code is hit, but the sorting is never applied to the results.
var results = new List<Location>();
var county = context.boc_County.Where(x => x.Description.Contains(phrase.ToLower())).ToList();
results.AddRange(_mapper.MapCountyFromDb(county));
var town = context.boc_Town.Where(x => x.Description.Contains(phrase.ToLower())).ToList();
results.AddRange(_mapper.MapTownFromDb(town));
if (orderBy == "Identifier")
{
if (direction == "ASC")
results = results.OrderBy(x => x.Identifier);
else
results = results.OrderByDescending(x => x.Identifier);
}
if (orderBy == "Type")
{
if (direction == "ASC")
results = results.OrderBy(x => x.LocationType.ToString());
else
results = results.OrderByDescending(x => x.LocationType.ToString());
}
if (orderBy == "Description")
{
if (direction == "ASC")
results = results.OrderBy(x => x.Description);
else
results = results.OrderByDescending(x => x.Description);
}
var model = new LocationSearchResult()
{
Locations = query.Skip(page * pageSize).Take(pageSize),
TotalCount = query.Count()
};
return model;
OrderBy and OrderByDescending don't change the caller, they return new IQueryable/IEnuemrable instead. You have to assign it back to another (or the same) variable. Otherwise calling them has no sense.
Because you're using List<T> you have to add additional ToList() call to make it compile and work:
if (orderBy == "Identifier")
{
if (direction == "ASC")
results = results.OrderBy(x => x.Identifier).ToList();
else
results = results.OrderByDescending(x => x.Identifier).ToList();
}
// (...)
or you can use List<T>.Sort instead:
if (orderBy == "Identifier")
{
if (direction == "ASC")
results.Sort((x1, x2) => x1.Compare(x2));
else
results.Sort((x1, x2) => x2.Compare(x1));
}

set a variable inside ajax function

Why does the usernameOK=1; statement in the ajax function not stay set when I use the alert statement after the $.post function? I need a way to use a variable as a condition for an if statement.
function validateRegistration() {
var username = document.getElementById("userName").value;
var fname = document.getElementById("fName").value;
var lname = document.getElementById("lName").value;
var email = document.getElementById("email").value;
var confirmEmail = document.getElementById("confirmEmail").value;
var password = document.getElementById("userpass").value;
var confirmPass = document.getElementById("confirmPassword").value;
var usernameOK = 0;
$.post("action.php", { field: 'doesUsernameExist', username: username },
function(result){ //if the result is 1
if(result == 1){ //show that the username is available
usernameSuc.innerHTML= username + " is Available.";
var usernameOK=1;
}else if(result == 0){ //show that the username is NOT available
usernameErr.innerHTML="User name: "+username+" is not
available.";
} else {
usernameErr.innerHTML="Something is Wrong";
}
});
alert("usernameOK: "+usernameOK); //This doesn't work. only prints a zero, never 1
if (usernameOK == 1) {
if ((username.length > 5) && (!(/[^a-zA-Z0-9_-]/.test(username)))){
if((fname != "") && (lname != "")){
if((email != "") && (email == confirmEmail)){
if (((email.indexOf(".") > 0) && (email.indexOf("#") > 0))
&& !/[^a-zA-Z0-9.#_-]/.test(email)){
if ((password.length > 7) && (/[a-z]/.test(password))
&& (/[A-Z]/.test(password)) && (/[0-9]/.test(password))){
if (password == confirmPass) {
document.getElementById("submit").className = "btn btn-success";
document.getElementById("submit").removeAttribute("disabled");
}
}
}
}
}
}
} else {
document.getElementById("submit").className = "btn btn-success disabled";
}
}
Figured out a solution. Thought I would post it in case it would help someone else. Changed the order and moved the ajax inside all the conditional if statements so it is the last thing to check instead of the first.
function validateRegistration() {
var username = document.getElementById("userName").value;
var fname = document.getElementById("fName").value;
var lname = document.getElementById("lName").value;
var email = document.getElementById("email").value;
var confirmEmail = document.getElementById("confirmEmail").value;
var password = document.getElementById("userpass").value;
var confirmPass = document.getElementById("confirmPassword").value;
if ((username.length > 5) && (!(/[^a-zA-Z0-9_-]/.test(username)))){
if((fname != "") && (lname != "")){
if((email != "") && (email == confirmEmail)){
if (((email.indexOf(".") > 0)
&& (email.indexOf("#") > 0))
&& !/[^a-zA-Z0-9.#_-]/.test(email)){
if ((password.length > 7)
&& (/[a-z]/.test(password))
&& (/[A-Z]/.test(password))
&& (/[0-9]/.test(password))){
if (password == confirmPass) {
$.ajax({
type: "POST",
url: "action.php",
data: {field: 'doesUsernameExist', username: username },
async: false,
success: function (result) {
if(result == 1) {
document.getElementById("submit").className = "btn btn-success";
document.getElementById("submit").removeAttribute("disabled");
} else {
document.getElementById("submit").className = "btn btn-success disabled";
document.getElementById("submit").setAttribute('disabled', true);
}
},
error: function (result) {
pass = "error"
alert("There was an error with the database");
}
});
}
}
}
}
}
} else {
document.getElementById("submit").className = "btn btn-success disabled";
document.getElementById("submit").setAttribute('disabled', true);
}
}

Resources