linq with entity order by desc - c#

I just want to order descending like this:
var query = from o in oEntite_T.ORDRE
where o.DATE_CREE >= datedeb && o.DATE_CREE <= datefin
orderby o.NO_ORDRE descending
select o;
It does not order descending, and I also tried:
var query = (from o in oEntite_T.ORDRE
where o.DATE_CREE >= datedeb && o.DATE_CREE <= datefin
select o).OrderByDescending(p => p.NO_ORDRE);
I got the same result. Is this because the component Devexpress?
linqServerModeSource_Ordre.KeyExpression = "NO_ORDRE;CODE_CLIENT";
linqServerModeSource_Ordre.QueryableSource = oOrdre_BL.Get_OrdreEntity(dateEdit_Deb_Ordre.DateTime, dateEdit_Fin_Ordre.DateTime);
gridControl_Liste_Ordres.DataSource = linqServerModeSource_Ordre;
My complete code:
public IQueryable<ORDRE> Get_OrdreEntity(DateTime datedeb, DateTime datefin)
{
try
{
IQueryable<ORDRE> LesListe;
Soft8Exp_ClientEntities oEntite_T = new Soft8Exp_ClientEntities();
var query = (from o in oEntite_T.ORDRE
where o.DATE_CREE >= datedeb && o.DATE_CREE <= datefin
select o).OrderByDescending(p => p.NO_ORDRE);
//var query = oEntite_T.ExecuteFunction<ORDRE>("qf").;
LesListe = query;
return LesListe;
}
catch (Exception excThrown)
{
throw new Exception("Err_02", excThrown);
}
}

From the code I see that you return the query object to some external infrastructure (set DataSource property of a devexpress component).
Then I'd day that this component just adds another .OrderBy to this query when it executes it object so your sorting is lost.
It seems to be very possible and logical since devexpress have their own sorting capabilities which seem to just override yours.
By setting DataSource you just provide a data set, and it is up to the component to add sorting, paging, etc.
So look at the component API in order to specify sorting that you need. Perhaps it has properties to do it.

Related

Add the query to have condition to use datediff function

How to use datediff function in EntityFramework Core when I query the database entity.
I have the following query.
var delegates = await (from tn in _context.TrainingNotification
join cd in _context.CourseDelegate on
new { did = tn.CourseDelegateId, nid = (int?)tn.NotificationTypeId } equals
new { did = cd.CourseDelegateId, nid = cd.NotificationTypeId }
where !cd.Disabled
&& statusToFilter.Contains(cd.StatusType.StatusTypeCode)
&& cd.NotificationTypeId == 1
&& System.Data.Linq.DateDiffDay(DateTime.UtcNow.Date, tn.Created.Date) == daysToBeReminded
select new CourseDelegateUser
{
CourseDelegateId = cd.CourseDelegateId,
UserGuid = cd.UserGuid,
NotifiedUtc = tn.Created
}).ToListAsync();
I would like to get only those records whose created date is 5 days older.
How to achieve this?
The code you're using in the query is a Non-Sargable Query which is a low performance query.
Whenever a query has to perform a function on a value in a row, that value cannot use an index. However if you switch the function to the value you're comparing, then SQL can use an Index.
Instead of:
System.Data.Linq.DateDiffDay(DateTime.UtcNow.Date, tn.Created.Date) == daysToBeReminded
Use something like
var createdOn = DateTime.UtcNow.Date.AddDays(daysToBeReminded);
&& tn.Created.Date == createdOn;

Update IQueryable result before using as join in next query

I need to use Linq to Entity Framework to query a LOCATION table to get the record of the location code with the MAX effective date, then use that result as a join in the next query.
I BELIEVE I need to do convert before the IQueryable is used, because I have that last clause in the second query where I want to exclude records where the FLOOR code is in the excludedSchools list. That excludedSchools list will have the newLocationCode in it.
So, I need to update the values in the IQueryable result before I use it. Can I do this? Here is my code:
using (var db = new TheContext())
{
IQueryable<LocationTable> locatinWithMaxEffDate =
(from lc in db.LocationTable
where lc.EFF_STATUS == "A" && lc.EFFDT <= DateTime.Now
group lc by lc.LOCATION into g
select g.OrderByDescending(x => x.EFFDT).FirstOrDefault()
);
foreach (var location in locatinWithMaxEffDate.ToList())
{
string newLocationCode;
if(codeMappingDictionary.TryGetValue(location.FLOOR, out newLocationCode))
{
// how do I update locatinWithMaxEffDate FLOOR value
// with newLocationCode so it works in the query below?
location.FLOOR = newLocationCode;
}
}
var query =
(from fim in db.PS_PPS_FIM_EE_DATA
join mloc in locatinWithMaxEffDate on fim.LOCATION equals mloc.LOCATION
where
fim.EMPL_STATUS == PsPpsFimEeData.EmployeeStatusValues.Active
&& fim.AUTO_UPDATE == PsPpsFimEeData.AutoUpdateValues.Enabled
&& includeJobCodes.Contains(fim.JOBCODE)
&& !excludedSchools.Contains(mloc.FLOOR)
select new PpsAdministratorResult
{
SchoolId = mloc.FLOOR,
Login = fim.OPRID,
EmployeeId = fim.EMPLID,
}
With the code above, the locatinWithMaxEffDate does not have the updated FLOOR values. I can see why this is, but can't seem to fix it.
So far, I have tried introducing another list to ADD() the new location record to, then casting that as an IQueryable, but I get an error about primitive vs concrete types.
I decided to make things easier on myself. Since both sets of data are very small (fewer than 1000 records each) I call take the entire set of data as an annonymous type:
using (var db = new TheContext())
{
IQueryable<LocationTable> locatinWithMaxEffDate =
(from lc in db.LocationTable
where lc.EFF_STATUS == "A" && lc.EFFDT <= DateTime.Now
group lc by lc.LOCATION into g
select g.OrderByDescending(x => x.EFFDT).FirstOrDefault()
);
var query =
(from fim in db.PS_PPS_FIM_EE_DATA
join mloc in locatinWithMaxEffDate on fim.LOCATION equals mloc.LOCATION
where
fim.EMPL_STATUS == PsPpsFimEeData.EmployeeStatusValues.Active
&& fim.AUTO_UPDATE == PsPpsFimEeData.AutoUpdateValues.Enabled
&& includeJobCodes.Contains(fim.JOBCODE)
select new PpsAdministratorResult
{
SchoolId = mloc.FLOOR,
Login = fim.OPRID,
EmployeeId = fim.EMPLID,
}
}
Then, just work with the two objects:
List<PpsAdministratorResult> administratorList = new List<PpsAdministratorResult>();
foreach (var location in query.ToList())
{
string newLocationCode;
if(schoolCodeMappings.TryGetValue(location.SchoolId, out newLocationCode)) // && newLocationCode.Contains(location.LOCATION))
{
location.SchoolId = newLocationCode;
}
if( !excludedSchools.Contains(location.SchoolId) )
{
administratorList.Add(location);
}
}
Now, I have the list I want.

Filtering data with multiple filter values

Hello fellow stackoverflowers,
I'm currently working on a project which gives me a bit of trouble concerning filtering data from a database by using multiple filter values. The filter happens after selecting the filters and by clicking a button.
I have 5 filters: Region, Company, Price, and 2 boolean values
Note that Region and Company are special dropdownlist with checkboxes which means the user can select one or more regions and company names.
I already made a few tests and came up with a incomplete code which works a bit but not to my liking.
Problems arise when one of my filters is NULL or empty. I don't really know how to process this. The only way i thought of was using a bunch of IF ELSE statements, but i'm starting to think that this will never end since there are so much possibilities...
I'm sure there is a far more easier way of doing this without using a bunch of IF ELSE statements, but i don't really know how to do it. If anyone could steer me in the right direction that would be appreciated. Thanks
Here is what i have right now (I haven't added the Price to the query for now):
protected void filterRepeater(List<int> regionIDs, string[] companyArray,
string blocFiltValue, bool bMutFunds, bool bFinancing)
{
DatabaseEntities db = new DatabaseEntities();
PagedDataSource pagedDsource = new PagedDataSource();
IQueryable<Blocs> query = (from q in db.Blocs
where q.isActive == true
orderby q.date descending
select q);
IQueryable<Blocs> queryResult = null;
//if some filters are NULL or Empty, it create a null queryResult
queryResult = query.Where(p => companyArray.Contains(p.company) &&
regionIDs.Contains((int)p.fkRegionID) &&
(bool)p.mutual_funds == bMutFunds &&
(bool)p.financing == bFinancing);
if (queryResult.Count() > 0)
{
//Bind new data to repeater
pagedDsource.DataSource = queryResult.ToArray();
blocRepeater.DataSource = pagedDsource;
blocRepeater.DataBind();
}
}
Only add the relevant filters to query:
IQueryable<Blocs> query =
from q in db.Blocs
where q.isActive == true
orderby q.date descending
select q;
if (companyArray != null)
{
query = query.Where(p => companyArray.Contains(p.company));
}
if (regionIDs != null)
{
query = query.Where(p => regionIDs.Contains((int)p.fkRegionID));
}
// ...
// etc
// ...
if (query.Any()) // Any() is more efficient than Count()
{
//Bind new data to repeater
pagedDsource.DataSource = query.ToArray();
blocRepeater.DataSource = pagedDsource;
blocRepeater.DataBind();
}
If you want to filter only by the filter values that are not null or empty then you can construct the query by appending the where clauses one by one:
if(companyArray != null && companyArray.Length > 0) {
query = query.Where(p => companyArray.Contains(p.company));
}
if(regionIDs!= null && regionIDs.Length > 0) {
query = query.Where(p => regionIDs.Contains((int)p.fkRegionID));
}
if (!String.IsNullOrEmpty(blocFiltValue)) {
query = query.Where(p => p.Block == blocFiltValue);
}
Also you can use nullable values for value types, if you need to filter them optionally
bool? bMutFunds = ...; // Possible values: null, false, true.
...
if(bMutFunds.HasValue) {
query = query.Where(p => (bool)p.mutual_funds == bMutFunds.Value);
}
Maybe you can create a string for the SQL sentence, and dynamically add parts to this sentence like if something was selected or checked you add something to this string when thh selection was completed by the user you can execute this SQL sentence.

Short Date in Linq

I want my query to stop displaying time and just the date. This is what I've tried to far:
Query= (from z in ctx.Interactions
where z.ActivityDate <= StartDateTo
&& z.ActivityDate >= EndDateTo
&& z.Indepth == false
select new
{
Date = new DateTime(z.ActivityDate.Year, z.ActivityDate.Month, z.ActivityDate.Day),
Subject = z.Subject
}).ToList();
And
Query= (from z in ctx.Interactions
where z.ActivityDate <= StartDateTo
&& z.ActivityDate >= EndDateTo
&& z.Indepth == false
select new
{
Date = z.ActivityDate.Date,
Subject = z.Subject
}).ToList();
And both didn't work.
LINQ to Entities does not recognize the method 'System.String ToString(System.String)' method, and this method cannot be translated into a store expression. when trying to apply a string method.
You can use anyDate.ToString("ddMMyyyy");//any preferred format.
Not sure if that is what you are looking for!
Your queries return objects with Date & Subject properties.
In the Date property you are passing a DateTime object. In order to display the short date you have a "ToShortDateString()" function on a date.
If you dont want to work with a date and prefer selecting a string, then do the conversion inside the linq query.
Use this if you want to return strings:
var q = (from z in ctx.Interactions
where z.ActivityDate <= StartDateTo && z.ActivityDate >= EndDateTo && z.Indepth == false
select new { Date = z.ActivityDate.Date.ToShortDateString(), Subject = z.Subject }).ToList();
You would need to perform the formatting at the time of the binding. As you don't show the actual binding code, it is hard to specifically address your situation but lets look at what happens in your query:
Query= (from z in ctx.Interactions
where z.ActivityDate <= StartDateTo && z.ActivityDate >= EndDateTo && z.Indepth == false
select new { Date = z.ActivityDate.Date, Subject = z.Subject }).ToList();
Once LINQ handles this query, the resulting Query variable should be of type List<DateTime>. The way you have the query working you would return a list of DateTimes in a format like this:
2014-04-23 00:00:00
2014-03-28 00:00:00
etc...
In order to bind this without the time value, you need to call ToString() on each element (or the desired element) of the list at the time of binding.
Assuming you are using a ListBox or something similar you could write the following:
foreach (var date in myList) //this is the resultant list from the query
{
listBox1.Items.Add(date.ToString("MM/dd/yyyy");
}
If you are literally binding to a DataSource property, you will need to convert your List<DateTime> to a List<string> with the formatted values.
ToShortDateString() may help you.
Query= (from z in ctx.Interactions
where z.ActivityDate <= StartDateTo
&& z.ActivityDate >= EndDateTo
&& z.Indepth == false
select new
{
Date = z.ActivityDate.ToShortDateString(),
Subject = z.Subject
}).ToList();
convert date into string like below
string stringDate=string.empty;
stringDate=Convert.ToDateTime("2014-04-23 00:00:00").ToShortDateString();
it will give output like
2014-04-23

DateTime WHERE Parameters

I have a gridview that is populated from an entitydatasource in asp.net. In my c# code-behind I need to add a WHERE parameter to the entity data source that will filter out all data that is not >= validDate1 and <= validDate2.
Here is where I'm at:
using (RamRideOpsEntities myEntities = new RamRideOpsEntities())
{
var validDates = (from a in myEntities.AdminOptions
select new { a.ValidDate1, a.ValidDate2 }).FirstOrDefault();
if (validDates != null)
{
RidesGridView.Where = " ..... ??? " //TODO
}
}
Edit: with the answers below, let me be more clear.. the validDates = .... statement is just getting the two valid dates I need to filter by.. there 'where' clause needs to be added to the entity data source so the data displayed in the grid view is within the valid date range.
You're using an EntityDataSource. This is a very un-linq type which allows you to use runtime-defined strings to modify queries. A more linq-ish technique would prefer that the string is part of the language of the program, and the compiler would turn it into an expression tree (as others have posted). That linq-ish approach won't work as long as you're using an EntityDataSource.
From the msdn article referencing EntityDataSource.Where, it looks like you need to use the magic word "it" to describe the row. Then you'd supply the parameters to the .WhereParameters collection.
Code:
using (myEntities = new RamRideOpsEntities())
{
var validDates = (from a in myEntities.AdminOptions
select new { a.ValidDate1, a.ValidDate2 }).FirstOrDefault();
if (validDates != null)
{
RidesEDS.Where = #"it.TimeOfCall >= #ValidDate1 AND it.TimeOfCall <= #ValidDate2";
RidesEDS.WhereParameters.Add(#"ValidDate1", DbType.DateTime, validDates.ValidDate1.ToString());
RidesEDS.WhereParameters.Add(#"ValidDate2", DbType.DateTime, validDates.ValidDate2.ToString());
}
}
var validDates = (from a in myEntities.AdminOptions where
a.ValidDate1 >= validDate1 && a.ValidDate2 <= validDate2
select new { a.ValidDate1, a.ValidDate2 }).FirstOrDefault();
You don't filter the GridView, you filter the data source. The answer will depend on what kind of data source you have, but assuming it's Linq-compatible:
var items = dataSource.Where(
d => d.Date >= validDates.ValidDate1 && d.Date <= validDates.ValidDate2
);
RidesGridView.DataSource = items;

Categories