IQueryable Sort not working - linq

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));
}

Related

LINQ: Cannot get more than two Where clauses to work

I cannot get the following to work properly. I want to search my database using more than 2 conditions where it will be possible to search only on one, two or all three, thus narrowing the search. At the moment, I can only get it to work with one condition at a time, and it only evaluates the first condition when having more than 3.
How can I Include more than 2 conditions? I have tried several proposed solutions from other sources, that uses if statements and where clauses, but so far none of them have worked.
This is my controller
public IActionResult Index(string searchString, int searchProject, string searchTitel)
{
var Projektdokumenter = from p in _context.ProjekterDokutypeDokuundertype
.Include(p => p.Dokumenttype)
.Include(p => p.Dokuundertype)
.Include(p => p.Forfatter)
.Include(p => p.P)
.Include(p => p.Sprog)
select p;
if (!String.IsNullOrEmpty(searchString) ^ searchProject != null ^ !String.IsNullOrEmpty(searchTitel))
{
if (!String.IsNullOrEmpty(searchString))
{
var c = Projektdokumenter.Where(p => p.Forfatter.Initialer.Contains(searchString)).ToList();
return View(c);
}
{
if (searchProject != 0)
{
var d = Projektdokumenter.Where(p => p.P.ProjektId.Equals(searchProject)).ToList();
return View(d);
}
{
if(!String.IsNullOrEmpty(searchTitel))
{
var f = Projektdokumenter.Where(p => p.Titel.Contains(searchTitel)).ToList();
return View(f);
}
}
}
}
var e = Projektdokumenter.Where(c.Contains(searchString) && p.P.ProjektId.Equals(searchProject) && p.Titel.Contains(searchTitel)).ToList();
return View(e);
}
IQueryable can be combined, so just write in native way:
{
var query = _context.ProjekterDokutypeDokuundertype
.Include(p => p.Dokumenttype)
.Include(p => p.Dokuundertype)
.Include(p => p.Forfatter)
.Include(p => p.P)
.Include(p => p.Sprog)
.AsQueryable();
if (!string.IsNullOrEmpty(searchString))
{
query = query.Where(p => p.Forfatter.Initialer.Contains(searchString));
}
if (searchProject != 0)
{
query = query.Where(p => p.P.ProjektId == searchProject);
}
if (!string.IsNullOrEmpty(searchTitel))
{
query = query.Where(p => p.Titel.Contains(searchTitel))
}
return View(query.ToList());
}

Elastic search NEST - filtered group sorting

I am new to the elastic search, I have done a bit of research but I could not find the right answer which fits to my requirement. The below query return the results of searched term and surrounding suburbs results together with the filter condition and I want to sort them individually, term search should always be on the top and surrounding suburbs at the bottom, I have done the aggregation so I know the count of search term results.
double firstTermLatForSort = 0;
double firstTermLngForSort = 0;
int requestedPage = request.Page > 0 ? request.Page - 1 : 0;
FilterContainer termFilters = new FilterContainer();
FilterContainer refineFilters = new FilterContainer();
FilterContainer surroundingFilters = new FilterContainer();
var exactMatches = await _elasticClient.SearchAsync<ResidentialDetails>(s => s
.From(requestedPage * request.PageSize)
.Size(request.PageSize > 0 ? request.PageSize : 20)
.Filter(f =>
{
refineFilters = f.Term(t => t.Status, "current");
FilterContainer filter = new FilterContainer();
if (request.Terms != null && request.Terms.Any())
{
var i = 1;
foreach (var term in request.Terms)
{
FilterContainer termFilter = new FilterContainer();
if (term.TermType == TermType.Suburb)
{
termFilter = f.Term(x => x.Address.Suburb, term.Term.ToLower());
if (i == 1)
{
firstTermLatForSort = term.Location.Latitude;
firstTermLngForSort = term.Location.Longitude;
}
}
else if (term.TermType == TermType.Region)
{
termFilter = f.Term(x => x.Address.Region, term.Term.ToLower());
}
else if (term.TermType == TermType.Council)
{
termFilter = f.Term(x => x.Address.Council, term.Term.ToLower());
}
else if (term.TermType == TermType.Postcode)
{
termFilter = f.Term(x => x.Address.Postcode, term.Term.ToLower());
}
if (term.TermType == TermType.State)
{
termFilters |= (f.Term(x => x.Address.StateAbbr, term.State.ToLower())
|| f.Term(x => x.Address.State, term.State.ToLower()));
}
else
{
termFilters |=
(termFilter
&& (f.Term(x => x.Address.StateAbbr, term.State.ToLower())
|| f.Term(x => x.Address.State, term.State.ToLower())));
if (request.SurroundingSuburbs)
{
surroundingFilters |= (f.GeoDistance(g => g.Address.Location, geoDistanceFilterDescriptor => geoDistanceFilterDescriptor
.Location(term.Location.Latitude, term.Location.Longitude)
.Distance("5km")
.DistanceType(GeoDistance.Arc)));
}
}
i++;
}
filter = filter && (termFilters || surroundingFilters);
}
if (request.PropertyType != null && request.PropertyType.Any())
refineFilters &= f.Terms(x => x.Category, request.PropertyType.Select(p => p.ToLower()));
if (request.PriceMin > 0)
refineFilters &= f.Range(r => r.OnField(x => x.Price.Price).GreaterOrEquals(request.PriceMin));
if (request.PriceMax > 0)
refineFilters &= f.Range(r => r.OnField(x => x.Price.Price).LowerOrEquals(request.PriceMax));
if (request.LandSizeMin > 0)
refineFilters &= f.Range(r => r.OnField(x => x.Dimensions.LandAreaSqMeters).GreaterOrEquals(request.LandSizeMin));
if (request.BedsMin > 0)
refineFilters &= f.Range(r => r.OnField(x => x.Features.Bedrooms).GreaterOrEquals(request.BedsMin));
if (request.BedsMax > 0)
refineFilters &= f.Range(r => r.OnField(x => x.Features.Bedrooms).LowerOrEquals(request.BedsMax));
if (request.BathsMin > 0)
refineFilters &= f.Range(r => r.OnField(x => x.Features.Bathrooms).GreaterOrEquals(request.BathsMin));
if (request.CarsMin > 0)
refineFilters &= f.Range(r => r.OnField(x => x.Features.TotalCarSpaces).GreaterOrEquals(request.CarsMin));
if (request.ExcludeUnderOffer)
{
refineFilters &= f.Term(x => x.UnderOffer, false);
}
filter = filter && (refineFilters);
return filter;
})
.Aggregations(ag =>
{
return ag.Filter("SearchTermMatchCount", st => st
.Filter(
f =>
{
return termFilters && refineFilters;
}).Aggregations(sag =>
{
return sag.Terms("SearchTermMatch", t => t.Field(sf => sf.Address.Suburb).OrderAscending("_term"));
} ));
})
.SortGeoDistance(sgd =>
{
if (request.Sort == Csn.Dto.Homesales.Enums.SortOrder.Distance)
{
return sgd.OnField(x => x.Address.Location)
.Order(Nest.SortOrder.Ascending)
.Unit(GeoUnit.Kilometers)
.Mode(SortMode.Min)
.DistanceType(GeoDistance.Plane)
.PinTo(firstTermLatForSort, firstTermLngForSort);
}
else
{
return null;
}
})
.Sort(st =>
{
switch (request.Sort)
{
case Csn.Dto.Homesales.Enums.SortOrder.LatestListing:
return st.OnField(x => x.DateCreated).Descending();
case Csn.Dto.Homesales.Enums.SortOrder.OldestListing:
return st.OnField(x => x.DateCreated).Ascending();
case Csn.Dto.Homesales.Enums.SortOrder.PriceHighest:
return st.OnField(x => x.Price.Price).Descending();
case Csn.Dto.Homesales.Enums.SortOrder.PriceLowest:
return st.OnField(x => x.Price.Price).Ascending();
default:
{
if (request.Sort != Csn.Dto.Homesales.Enums.SortOrder.Distance)
{
return st.OnField(x => x.AdPriority).Descending();
}
else
{
return null;
}
}
}
}
)
);
response.Matches = exactMatches.Documents.ToList();
response.Count = exactMatches.Total;
var aggregation = (SingleBucket)exactMatches.Aggregations.Where(a=>a.Key == "SearchTermMatchCount").Select(a => a.Value);
response.SearchTermMatchCount = aggregation.DocCount;
With the above query I am getting something like, if search with the term : Kotara (which is a suburb), I get the result for that suburb and also surrounding suburbs with in the range of 5km.
propertyId:1, address.suburb: "charlestown", price:500,000 (1 record which is surrounding suburb)
propertyId:2, address.suburb: "kotara", price:500,000 (2nd record, searched term)
PropertyId:14, address.suburb:"Newcastle", price:400,000(3rd record, surrounding),
propertyId: 4, address.suburb: "kotara", price:200,000 (4th record, searched term)
But I want the result like
propertyId:2, address.suburb: "kotara", price:500,000 (1st record, searched term)
propertyId: 4, address.suburb: "kotara", price:200,000 (2nd record, searched term)
propertyId:1, address.suburb: "charlestown", price:500,000 (3rd record which is surrounding suburb)
PropertyId:14, address.suburb:"Newcastle", price:400,000(3rd record, surrounding)
All the "searched term" results should be at the top of the sorting then all the other sorting conditions should come

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();
}

OrderByDescending linq query

I am trying to show deal.type as decending order by date but I cannot get the result to show in Descending order.
[Authorize(Roles = "admin")]
[HttpGet]
[Queryable(PageSize = 10)]
public HttpResponseMessage Get([FromUri] Query query)
{
var data = db.database_ICs.AsQueryable();
if (query.price_type != null)
{
data = data.Where(c => c.Cover == query.price_type);
}
if (query.deal_type != null)
{
data = data.Where(c => c.Type == query.deal_type)
.OrderByDescending(c => c.UploadDate);
}
if (query.startDate != null)
{
data = data.Where(c => c.UploadDate >= query.startDate);
}
if (query.endDate != null)
{
data = data.Where(c => c.UploadDate <= query.endDate);
}
if (!data.Any())
{
var message = string.Format("No data was found");
return Request.CreateErrorResponse(HttpStatusCode.NotFound, message);
}
return Request.CreateResponse(HttpStatusCode.OK, data);
}
Any help would be very much appreciated.
Please, try change this:
[Queryable(PageSize = 10)]
For this:
[Queryable(PageSize = 10, EnsureStableOrdering = false)]
More informations here.
Hope that helps!
See ya!

Ordering in LINQ Statement Ineffective

I'm having trouble getting some ordering working in a LINQ statement I've been working on. Here is the code:
public static List<Contact> GetAllTheCusts(string fName,
string lName,
string middleName,
int? customerId,
string sort,
int pageIndex,
int pageSize)
{
AWEntities entities = Common.GetContext();
int skipCount = pageSize * pageIndex;
var contacts = entities.Contacts
.Include("Individuals.Customer")
.Where(c => customerId.HasValue
? c.Individuals.Any(i => i.CustomerID == customerId.Value)
: c.Individuals.Any(i => i.Customer.CustomerID == i.CustomerID))
.Where(c => string.IsNullOrEmpty(fName) || c.FirstName.Contains(fName))
.Where(c => string.IsNullOrEmpty(lName) || c.LastName.Contains(lName))
.Where(c => string.IsNullOrEmpty(middleName) || c.MiddleName.Contains(middleName));
.Select(c => c);
IOrderedQueryable<Contact> contactsOrdered = contacts.OrderByDescending(o => o.ContactID);;
return contactsOrdered.Skip(skipCount).Take(pageSize).ToList();
}
For some reason, the OrderByDescending method is not performing its role. Can anybody help please.
Cheers
Thought I would post the final working code here. This has successfully converted the stored procedure to LINQ-to-Entities:
public static List<Contact> GetCustomersWithContactDetails(string fName, string lName, string middleName, int? customerId,
string sort, int pageIndex, int pageSize, out int count)
{
AWEntities entities = Common.GetContext();
int skipCount = pageSize * pageIndex;
var contacts = entities.Contacts
.Include("Individuals.Customer")
.Where(c => customerId.HasValue
? c.Individuals.Any(i => i.CustomerID == customerId.Value)
: c.Individuals.Any(i => i.Customer.CustomerID == i.CustomerID))
.Where(c => string.IsNullOrEmpty(fName) || c.FirstName.Contains(fName))
.Where(c => string.IsNullOrEmpty(lName) || c.LastName.Contains(lName))
.Where(c => string.IsNullOrEmpty(middleName) || c.MiddleName.Contains(middleName));
// Get ordering based on the "sort" parameter
var contactsOrdered = GetOrdering(sort, contacts);
count = contacts.Count();
return contactsOrdered.Skip(skipCount).Take(pageSize).ToList();
}
private static IOrderedQueryable<Contact> GetOrdering(string sort, IQueryable<Contact> contacts)
{
IOrderedQueryable<Contact> contactsOrdered;
if (string.IsNullOrEmpty(sort))
{
contactsOrdered = contacts.OrderBy(o => o.LastName);
}
else
{
SortDirection sortDirection = sort.EndsWith("ASC", StringComparison.Ordinal)
? SortDirection.asc
: SortDirection.desc;
switch (sort.Substring(0, sort.IndexOf(' ')))
{
case "ContactID":
{
if (sortDirection == SortDirection.asc)
{
contactsOrdered = contacts.OrderBy(o => o.ContactID);
}
else
{
contactsOrdered = contacts.OrderByDescending(o => o.ContactID);
}
break;
}
case "LastName":
{
if (sortDirection == SortDirection.asc)
{
contactsOrdered = contacts.OrderBy(o => o.LastName);
}
else
{
contactsOrdered = contacts.OrderByDescending(o => o.LastName);
}
break;
}
case "FirstName":
{
if (sortDirection == SortDirection.asc)
{
contactsOrdered = contacts.OrderBy(o => o.FirstName);
}
else
{
contactsOrdered = contacts.OrderByDescending(o => o.FirstName);
}
break;
}
case "MiddleName":
{
if (sortDirection == SortDirection.asc)
{
contactsOrdered = contacts.OrderBy(o => o.MiddleName);
}
else
{
contactsOrdered = contacts.OrderByDescending(o => o.MiddleName);
}
break;
}
default:
{
contactsOrdered = contacts.OrderBy(o => o.ContactID);
break;
}
}
}
return contactsOrdered;
}
Cheers

Resources