Here is my code and i want to order by via date_added column. i tried all the possibilities but still the date_added column sorted via month instead of a year. Please guide where i need to put orderby statement.further the date_added return result in string datatype.
{
var records = (from r in db2.documents
select new
{
r.show_in_portal,
r.buyer_id,
r.advertiser_id,
r.contract_id,
r.campaign_id,
date_added = Dates.FormatDateToExt(r.date_added),
id = r.document_id,
name = r.filename,
location = r.filename,
r.publisher_id,
affiliate_id = (r.contract != null ? r.contract.publisher_id : -1),
document_type = r.document_type.type_name
});
if (campaign_id > 0)
records = records.Where(v => v.campaign_id == campaign_id);
//if (creativeid > 0)
// records = records.Where(v => v.id == creativeid);
if (affid > 0)
records = records.Where(v => v.publisher_id == affid);
if (contid > 0)
records = records.Where(v => v.contract_id == contid);
if (advertiserid > 0)
records = records.Where(v => v.advertiser_id == advertiserid);
if (buyerid > 0)
records = records.Where(v => v.buyer_id == buyerid);
GridOut(context, records.ToArray());
}
public static string FormatDateToExt(DateTime? input)
{
return FormatDateToExt(input, 0);
}
public static string FormatDateToExt(DateTime? input, int time_offset = 0)
{
return input != null ? input.Value.AddHours(-1 * time_offset).ToString("MM/dd/yyy h:mm:ss tt") : "";
}
The result of your query is a sequence of some anonymous type. Date_Added is one of the properties of this anonymous type, so after you created your query you can order by Date_Added.
The type of Date_Added is the returned type of Dates.FormatDateToExt(...). Alas you forgot to inform us about this type. Is it a DateTime? Is it a string? If you order by this type do you get the sorting order that you want?
If so, just add the OrderBy at the end:
var records = db2.documents.Select(document => new
{
Id = document.document_id,
Portal = document.Show,
BuyerId = document.buyer_id,
AdvertiserId = document.advertiser_id,
...
DateAdded = Dates.FormatDateToExt(document.date_added),
});
if (campaign_id > 0)
records = records.Where(record => record.campaign_id == campaign_id);
if (affid > 0)
records = records.Where(record => record.publisher_id == affid);
... // etc. other ifs and other wheres
records = records.OrderBy(record => record.DateAdded);
It is a good thing to do the Sorting at the end, because this means that you will have to sort fewer records. All records that don't pass all Wheres, won't have to be sorted.
Finally a small hint: did you see, that if you use proper identifiers, that your queries will be easier to read? It is good practice to use plural nouns for collections of items, and singular nouns for elements of the collection:
var novels = dbContext.Books.Where(book => book.Type == BookType.Novel)
Consider making your dates uniform by using ISO 8601 ones (convert them on the fly in your Linq query), as they're made to be sortable.
You can put the orderby clause after the from.
Read:
https://www.c-sharpcorner.com/UploadFile/mahesh/working-with-datetime-using-C-Sharp/
https://dev.to/adnauseum/sorting-iso-8601-timestamps-5am2
Related
I want to take a list of items from a table, apply grouping logic(grouping by assignment type, start and end time), and then convert back to starting type.
IEnumerable<Assignment> assignments = UnitOfWork.AssignmentRepository.Get(filter: a => a.Start.CompareTo(start) >= 0
&& a.End.CompareTo(end) <= 0,
orderBy: o => o.OrderBy(a => a.Start));
List<Assignment> pre_alerts = new List<Assignment>();
foreach (Assignment a in assignments)
{
foreach (AssignmentType t in assignmentTypes)
{ // determine if the assignment's type has a minimum required
if (a.AssignmentTypeID == t.AssignmentTypeID && t.Minimum>0)
{
// get the minimum assignments requierd
int min_required = t.Minimum;
DateTime s = a.Start;
DateTime e = a.End;
AssignmentType type = a.AssignmentType;
IEnumerable<Assignment> minimum_assignments = UnitOfWork.AssignmentRepository.Get(filter: m => m.Start.CompareTo(s) >= 0 && m.End.CompareTo(e) <= 0 && m.AssignmentTypeID == a.AssignmentTypeID, orderBy: o => o.OrderBy(m => m.Start));
int min_actual = minimum_assignments.Count();
if (min_actual < min_required)
{
// add a single alert for time range and assignment type
pre_alerts.Add(a);
}
}
}
}
var alerts = pre_alerts.GroupBy(x => new Assignment{ x.AssignmentTypeID, x.Start, x.End }).Select(k => k);
how do I convert alerts to IEnumerable<Assignment> ?
When using Select you are already returning it as an IEnumerable. If you want it to be of your type then:
var alerts = pre_alerts.GroupBy(x => new Assignment{ x.AssignmentTypeID, x.Start, x.End }).Select(k => k.Key);
The result of a GroupBy is an IGrouping so by Selecting just k you are returning an IEnumerable<IGrouping<Assignment...>>
But it feels to me that if that is the case then there is no reason to use the GroupBy but just Select to create the assignments and then distinct
I have the below LINQ query that performs a self-left-outer-join. The querys looks a little complex but is simply doing a self join on itself(purpose if to join each record with the record for it previous business day) and then doing some parameterized filtering.
var newBreakThreshold = decimal.Parse(WebConfigurationManager.AppSettings["NewBreakThreshold"]);
using (var dbContext = new NavFoToBoCompareDbContext())
{
var query = from current in dbContext.NAVSummaries
let currentWD = SqlFunctions.DatePart("dw", current.ValueDate)
let currentPD = DbFunctions.AddDays(current.ValueDate, currentWD == 2 ? -3 : currentWD == 1 ? -2 : -1).Value
join previous in dbContext.NAVSummaries
on new { current.Portfolio, PD = currentPD }
equals new { previous.Portfolio, PD = previous.ValueDate }
into previousGroup
from previous in previousGroup.DefaultIfEmpty() // LEFT OUTER JOIN
select new { outer = current, inner = previous };
if (dateStart.HasValue)
query = query.Where(e => e.outer.ValueDate >= dateStart.Value);
if (dateEnd.HasValue)
query = query.Where(e => e.outer.ValueDate <= dateEnd.Value);
if (!portfolio.Equals("ALL", StringComparison.OrdinalIgnoreCase))
query = query.Where(e => e.outer.Portfolio.Equals(portfolio, StringComparison.OrdinalIgnoreCase));
if (!owner.Equals("ALL", StringComparison.OrdinalIgnoreCase))
query = query.Where(e => e.outer.PortfolioOwner.Equals(owner, StringComparison.OrdinalIgnoreCase));
if (status != 0)
query = query.Where(e => e.outer.Statuses.Any(s => s.StatusId == status));
var query2 = query.Select(s => new
{
BackOfficeNAV = s.outer.BackOfficeNAV,
FrontOfficeNAV = s.outer.FrontOfficeNAV,
Threshold = s.outer.Threshold,
ExtractId = s.outer.ExtractId,
ExtractStatus = s.outer.ExtractStatus,
PortfolioOwner = s.outer.PortfolioOwner,
DateTimeModified = s.outer.DateTimeModified,
MostCorrectNAV = s.outer.MostCorrectNAV,
Comments = s.outer.Comments,
Statuses = s.outer.Statuses,
Extracts = s.outer.Extracts,
Portfolio = s.outer.Portfolio,
ValueDate = s.outer.ValueDate,
DifferencePercent = s.outer.DifferencePercent,
DayOverDayChange = s.outer.DifferencePercent - s.inner.DifferencePercent,
IsChange = s.inner.DifferencePercent != s.outer.DifferencePercent,
PreviousValueDate = s.inner.ValueDate,
PreviousDifferencePercent = s.inner.DifferencePercent
});
query2 = query2.Where(r => "NEW".Equals(breakOption, StringComparison.OrdinalIgnoreCase) ?
((r.DifferencePercent > r.Threshold) && r.IsChange && r.DayOverDayChange > newBreakThreshold) :
"OLD".Equals(breakOption, StringComparison.OrdinalIgnoreCase) ? (r.DifferencePercent > r.Threshold) :
"ALL".Equals(breakOption, StringComparison.OrdinalIgnoreCase));
var resultCount = query2.Count();
}
The query is used in two places. In one method it used for computing the count required for pagination. In another method it is used for getting the actual results from the database. The implementation for getting the actual results for a bigger result set executes successfully, whereas the the Count() query fails with a Timeout exception. Note:Both implementations are exactly the same.
Can someone help me in optimizing this query as well. Thanks in advance.
Not quite sure that's the problem, but at least let try to eliminate the potential effect of the so called Parameter Sniffing Problem by eliminating the dateStart / dateEnd parameters by manually building expression with constant values.
First, a little helper method:
using System;
using System.Linq;
using System.Linq.Expressions;
public static class QueryableUtils
{
public static IQueryable<T> WhereBetween<T>(this IQueryable<T> source, Expression<Func<T, DateTime>> dateSelector, DateTime? startDate, DateTime? endDate)
{
if (startDate == null && endDate == null) return source;
var startCond = startDate != null ? Expression.GreaterThanOrEqual(dateSelector.Body, Expression.Constant(startDate.Value)) : null;
var endCond = endDate != null ? Expression.LessThanOrEqual(dateSelector.Body, Expression.Constant(endDate.Value)) : null;
var predicate = Expression.Lambda<Func<T, bool>>(
startCond == null ? endCond : endCond == null ? startCond : Expression.AndAlso(startCond, endCond),
dateSelector.Parameters[0]);
return source.Where(predicate);
}
}
Then try the following and see if it helps:
//if (dateStart.HasValue)
// query = query.Where(e => e.outer.ValueDate >= dateStart.Value);
//if (dateEnd.HasValue)
// query = query.Where(e => e.outer.ValueDate <= dateEnd.Value);
query = query.WhereBetween(e => e.outer.ValueDate, dateStart, dateEnd);
You can simply use AsParallel() to enable multithreading execution of the linq query.
You should then check your tables' indexes to improve performances.
I'm trying to fetch recent contents of each type, currently I'm using something similar to the following code to fetch n records for each type
int n = 10;
var contents = Entities.OrderByDescending(i => i.Date);
IQueryable<Content> query = null;
for (int i = 1; i<=5; i++)
{
if (query == null)
{
query = contents.Where(c => c.ContentTypeIndex == i).Take(n);
}
else
{
query = query.Concat(contents.Where(c => c.ContentTypeIndex == i).Take(n));
}
}
One other solution can be creating an SP, but is it possible to do it by grouping in EF? If not, any cleaner solution?
contents.Where(c => c.ContentTypeIndex >= 1 && c.ContentTypeIndex <= 5)
.GroupBy(c => c.ContentTypeIndex)
.SelectMany(g => g.Take(n));
Note: if you want to select all types of indexes, then you don't need where filter here.
I have this code:
List<jogo> lista_realizados = tt.jogo.Where(c => c.activo == 1 &&
c.progresso == 2 &&
c.id_torneio == torn.id_torneio)
.ToList();
var q1 = lista_realizados.Select(c => new { resultado = c.resultado,
id = c.id_jogo,
torneio = c.torneios.nome,
Data = c.data,
Hora = c.hora,
jogador = c.jogador.Nome_jogador,
jogador2 = c.jogador2.Nome_jogador,
Clube = c.clubeparceiro.nome,
agendadopor = c.alterado_por})
.OrderByDescending(p => p.Data.Value.Month )
.ToList();
gvListaJogos.DataSource = q1;
gvListaJogos.DataBind();
I get the list and then I try to order the list by the field Data - it is defined as a Date in sql. And in the code appeared as a ?Datetime.
But it seems that the list is being ordered by string and not by the date.
I'm guessing that gvListaJogos is a ListBox.
Make sure the Sorted property of the ListBox is set to false.
I have the following controller code that returns a Json list object to my view that draws a pie chart.
There are 4 input parameters and i have it working with 3 of them.
However, the fist parameter entitled 'SiteTypeId' needs to be included in the where.
My problem is how to include this neatly in the code, i'd like to avoid an override of the function.
The required additional logic is:
if SiteTypeId = -1 (then this means show all so nothing is to be changed)
if SiteTypeId = 0 (then i.SiteTypeId == 0 needs to be added)
if SiteTypeId = 1 (then i.SiteTypeId == 1 needs to be added)
If 2 and 3 above were all that was required it would be easy I guess. I'm thinking there must be a neat expression for this or a neat way of splitting the LINQ into 2 with a condition perhaps.
I'm new to LINQ - can anyone advise me, here is the controller code i need to modify:
public JsonResult GetChartData_IncidentsBySiteStatus(string SiteTypeId, string searchTextSite, string StartDate, string EndDate)
{
if (searchTextSite == null)
searchTextSite = "";
DateTime startDate = DateTime.Parse(StartDate);
DateTime endDate = DateTime.Parse(EndDate);
var qry = from s in _db.Sites
join i in _db.Incidents on s.SiteId equals i.SiteId
where s.SiteDescription.Contains(searchTextSite)
&& (i.Entered >= startDate && i.Entered <= endDate)
group s by s.SiteStatus.SiteStatusDescription + "[" + s.SiteTypeId.ToString() + "]"
into grp
select new
{
Site = grp.Key,
Count = grp.Count()
};
return Json(qry.ToList() , JsonRequestBehavior.AllowGet);
}
Sounds like you could use LINQKit and its PredicateBuilder. You use it to build dynamic conditional WHERE clauses. It's also used in LinqPad, and it's free.
Try this:
public JsonResult GetChartData_IncidentsBySiteStatus(string SiteTypeId, string searchTextSite, string StartDate, string EndDate)
{
if (searchTextSite == null)
searchTextSite = "";
DateTime startDate = DateTime.Parse(StartDate);
DateTime endDate = DateTime.Parse(EndDate);
var incidentsQry = _db.Incidents;
if(SiteTypeId > -1)
{
incidentsQry = incidentsQry.Where(a=>a.SiteTypeId == SiteTypeId);
}
var qry = from s in _db.Sites
join i in incidentsQry on s.SiteId equals i.SiteId
where s.SiteDescription.Contains(searchTextSite)
&& (i.Entered >= startDate && i.Entered <= endDate)
group s by s.SiteStatus.SiteStatusDescription + "[" + s.SiteTypeId.ToString() + "]"
into grp
select new
{
Site = grp.Key,
Count = grp.Count()
};
return Json(qry.ToList() , JsonRequestBehavior.AllowGet);
}
Simply add the following to your where clause
(SiteTypeId == -1 || i.SiteTypeId == SiteTypeId)