Using PagedList to add paging function to ASP MVC3 website - asp.net-mvc

One of the search functions to our website returns far too many results for one page to handle, so I am trying to add the paging function as provided by here: https://github.com/TroyGoode/PagedList
The solution builds properly and the page will load as well, however when I try to conduct a search a "NotSupportedException" is thrown on the page's controller/Index() method:
The method 'Skip' is only supported for sorted input in LINQ to Entities. The method 'OrderBy' must be called before the method 'Skip'.
Visual Studio 2010 points to the return statement when this exception is thrown. This is only my second day working in ASP MVC so any and all suggestion are welcome. Thank you!
case "name":
//if no comma, do a combined search by last name and by corporate name.
searchString = searchString.ToUpper();
var lastAgents =
db.Agent.OrderBy(s => s.LastName).Where(s => s.LastName.ToUpper().StartsWith(searchString)).Include(
a => a.AgentIdentification).Include(a => a.SymetraNumberToAgentId);
//end new code
var corp2Agents =
db.Agent.OrderBy(s => s.CorporateName).Where(s => s.CorporateName.ToUpper().StartsWith(searchString)).Include(
a => a.AgentIdentification);
if ((corp2Agents.Count() == 0) & (lastAgents.Count() == 0)) ViewBag.ErrorMessage = "None found in search for Last Names and Companies beginning with " + search1;
else ViewBag.Message = "Results of Last Name and Company Name search. Found " + (corp2Agents.Count() + lastAgents.Count()).ToString();
pageNumber = (page ?? 1);
return View(lastAgents.Union(corp2Agents).ToPagedList(pageNumber, pageSize));

Took forever but I found the answer. Both these statements
var lastAgents =
db.Agent.OrderBy(s => s.LastName).Where(s => s.LastName.ToUpper().StartsWith(searchString)).Include(
a => a.AgentIdentification).Include(a => a.SymetraNumberToAgentId);
//end new code
var corp2Agents =
db.Agent.OrderBy(s => s.CorporateName).Where(s => s.CorporateName.ToUpper().StartsWith(searchString)).Include(
a => a.AgentIdentification);
contain an OrderBy, however this is necessary in the Union statement as well. The final "return" statement is as follows:
return View((lastAgents.Union(corp2Agents)).OrderBy(s => s.sNumber).ToPagedList(pageNumber, pageSize));

Try adding the .OrderBy(s => s.sNumber) in the controller like this:
var lastAgents =
db.Agent.Where(s => s.LastName.ToUpper().StartsWith(searchString)).Include(
a => a.AgentIdentification).Include(a => a.SymetraNumberToAgentId).OrderBy(s => s.sNumber);
//end new code
var corp2Agents =
db.Agent.Where(s => s.CorporateName.ToUpper().StartsWith(searchString)).Include(
a => a.AgentIdentification).OrderBy(s => s.CorporateName);

Related

DraftProjectResource->IsGenericResource returning wrong value

I am using CSOM to traverse through Project Server 2013 resources on a project. I am checking if the resources are generic since I have written code logic based on that. I have a BA and PM generic resources that are part of a project that I added using the Build Team feature in Project Server. These resources show up with the Generic flag checked ON when viewing them in resource center. But programmatically the IsGenericResource flag is returning False.
Here is the code snippet (relevant code within **) :
public string ProcessGenericResources(ProjectContext pc, PublishedProject publishedproject)
{
try
{
Boolean bStaffingRequestItemUpdated = false; // this will be set to True whenever a staffing list item is update
string sResourceApproverAttr = ExceptionUtility.ReadKeyFromConfig(sResourceApproverKey);
string sRet = "";
DraftProject project;
if (publishedproject.IsCheckedOut)
project = publishedproject.Draft.IncludeCustomFields;
else
project = publishedproject.CheckOut().IncludeCustomFields;
pc.Load(project, p => p.Name, p => p.Id);
DraftProjectResourceCollection ProjectResources = project.ProjectResources;
pc.Load(ProjectResources, list => list.Include(item => item.Name, item => item.Id, item => item.IsGenericResource));
pc.ExecuteQuery();
// For each generic resource, check if an item is already in the Staffing Request list. If not create one
foreach (DraftProjectResource resource in ProjectResources)
{
List<string> listRMsNotified = new List<string>(); // this is to keep track of RMs already notified
pc.Load(resource);
pc.ExecuteQuery();
**bool bGenericResource = resource.IsGenericResource;
ExceptionUtility.LogMessage("Resource=> Name:" + resource.Name + " ID:" + resource.Id + " Is Generic Resource?: " + bGenericResource);**
I found the issue. Apparently ProjectResource is not the same as EnterpriseResource. For each ProjectResource in a Project you will need to find a match in the ProjectContext.EnterpriseResources collection. The record in EnterpriseResources collection shows the correct value in the IsGeneric attribute.

MVC EF select multiple joins

I have the following DB structure.
I want to make a select using Entity Framework. I want all my Categories that MAY have a CategoryText. If They have a CategoryText I also need to get the Language.
I searched and I couldn't find anything useful.
Here is my query that doesn't work:
var categoriesSQL = db.Categories
.Include(i => i.CategoryTexts.Select(s => s.Language)
.Where(w => w.Format == (string)Session["chosen_language"]));
var categories = categoriesSQL.ToList();
It throws:
The Include path expression must refer to a navigation property defined on the type. Use dotted paths for reference navigation properties and the Select operator for collection navigation properties.
Parameter name: path
I tried to solve this in a lot of ways and recomandations but I couldn't find a solution.
I want the select made in only one query.
Thank you!
Try this
var language = (string)Session["chosen_language"];
var categoriesSQL = db.Categories
.Include(i => i.CategoryTexts.Select(s => s.Language))
.Where(c =>
(from ct in c.CategoryTexts
from l in ct.Languages
select l.Format).Contains(language)
);
var categories = categoriesSQL.ToList();
OR
var language = (string)Session["chosen_language"];
var categoriesSQL = db.Categories
.Include(i => i.CategoryTexts.Select(s => s.Language))
.Where(c => c.CategoryText
.Any(ct => ct.Languages
.Any(l => l.Format == language)
)
);
var categories = categoriesSQL.ToList();

Unable to catch if a list item name is missing

I have the following code which groupBY my table and select the count based on the model name:-
var IT360Counts = entities.Resources.Where(a => String.IsNullOrEmpty(a.ASSETTAG) && (a.SystemInfo.ISSERVER == true))
.GroupBy(a => a.SystemInfo.MODEL.ToLower())
.Select(g => new
{
Action = g.Key.ToLower(),
ItemCount = g.Count()
}).ToLookup(a => a.Action);
Then i will referecne the var content such as :-
IT360RouterNo = IT360Counts["router"] == null ? 0 : IT360Counts["router"].SingleOrDefault().ItemCount,
The above will work well, unless when the first query does not have any router, then the second statement will always return null exception. so my question is weather there is a way to catch if IT360Counts["router"] exists sor not ?
Thanks
This will happen when IT360Counts["router"] is not null but an empty list. In that case IT360Counts["router"].SingleOrDefault() will return null, so when accessing its ItemCount property you will get a null exception.
This happens because the indexer in the Lookup returns an empty list when the key is not found. See remarks section in msdn. Try checking if the lookup contains the key, IT360Counts.Contains("router"). This way you can do:
IT360RouterNo = IT360Counts.Contains("router") ? IT360Counts["router"].SingleOrDefault().ItemCount : 0,
As a side note, have you also considered using ToDictionary instead of ToLookup? The dictionary key would be your Action and the value the ItemCount, so when retrieving the values you just get the value in the dictionary for a key like "router". If you are you always doing .SingleOrDefault().ItemCount and never expect more than one item with the same Action, you may be better using a dictionary.
For the sake of completion this idea would be:
var IT360Counts = entities.Resources.Where(a => String.IsNullOrEmpty(a.ASSETTAG) &&(a.SystemInfo.ISSERVER == true))
.GroupBy(a => a.SystemInfo.MODEL.ToLower())
.Select(g => new
{
Action = g.Key.ToLower(),
ItemCount = g.Count()
}).ToDictionary(a => a.Action, a => a.ItemCount);
IT360RouterNo = IT360Counts.ContainsKey("router") ? IT360Counts["router"] : 0,
Hope it helps!

How to calculate total cart value from knockout mvc cart sample

I am trying to get my head around knockout mvc framework. I am looking at the sample of a shopping cart and trying to figure out:
How to calculate total cost
Where to add client side business rules (such as discounts and vouchers)
To calculate subtotal the code reads
#using (lines.If(m => m.ProductId != -1))
{
using (var product = lines.With(m => ko.Model.DataBase[m.CategoryId].Products[m.ProductId]))
{
#product.Html.Span(m => "\\$" + m.Price)
}
}
When I try to get the total from there I usually end up with a compiler exception or NullReferenceException in run time. For example
#using (lines.If(m => m.ProductId != -1))
{
using (var product = lines.With(m => ko.Model.Categories[m.CategoryId].Products[m.ProductId]))
{
#product.Html.Span(m => "\\$" + (lines.Model.Quantity * m.Price))
#{double total = lines.Model.Quantity * m.Price;}
}
}
Gives me
Compiler Error Message: CS1501: No overload for method 'Write' takes 0
arguments
Seems like I am doing it wrong. Would anyone point me in a right direction?
Have you tried removing the # symbol from the start of each line? I'm sure once you open a razor code block, you don't need to keep prepending every line with #. Also, not sure why the 'double total' line is wrapped in {}?
#using (var product = lines.With(m => ko.Model.Categories[m.CategoryId].Products[m.ProductId]))
{
product.Html.Span(m => "\\$" + (lines.Model.Quantity * m.Price));
double total = lines.Model.Quantity * m.Price;
}

I want take the last 4 record but always get the first 4

I have this in my method:
var qry = db.Forms.Take(4)
.Where(m => m.SateliteID == Id)
.OrderByDescending(m => m.Tanggal)
.ToArray();
What I want is getting the last 4 records from all the records available, but
what I get is the first 4 records.
What I have done wrong?
I thought that command will be the same with this:
SELECT TOP 4 <fields> FROM Forms WHERE sateliteID = Id
ORDER BY tanggal DESC
But it seems they are a different.
What should I do to get what I want (the last 4 records instead of the first 4 records)?
Thanks in advance for the help.
Move your Take:
var qry = db.Forms.Where(m => m.SateliteID == Id)
.OrderByDescending(m => m.Tanggal)
.Take(4)
.ToArray();
var qry = db.Forms.Where(m => m.SateliteID == Id).OrderByDescending(m => m.Tanggal).Take(4).ToArray();
You should order and than take some results from ordered list. Methods should be called in that kind of order.
JUST get apply you where and orderby clause first and than apply take function that will do the work for you
var qry = db.Forms
.Where(m => m.SateliteID == Id)
.OrderByDescending(m => m.Tanggal)
.Take(4)
.ToArray();
For future use :LINQER
this will allow you to convert you SQL QUERIES TO LINQ easily.....very helpful tool

Resources