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;
Related
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;
I wanted to search for multiple values from the same column using OR in linq. In SQL, it is something like this:
var query = "Select * from table where id = 1";
query += "OR where id = 2";
The id is from an array of ids so i pass the id to a variable and loop it. The number of id in the array is not fixed and depends on how many ids chosen by the user by checking on the checkbox in the table. Because if i do as below, it will return null because it somewhat inteprets my where query as AND. How do i change it so that it will get rows from all ids(using OR)?
Request request = db.Requests;
var selectedIdList = new List<string>(arrId);
if (arrId.Length > 0)
{
for (var item = 0; item <= selectedIdList.Count() - 1; item++)
{
var detailId = Convert.ToInt32(selectedIdList[item]);
request = request.Where(y => y.Id == detailId);
}
}
Simply use || for OR and && for AND inside Where
But I prefer :
request.Where(y => selectedIdList.Contains(y.Id));
If selectedIdList is an array of Strings :
request.Where(y => selectedIdList.Contains(y.Id.ToString());
You can use LinqKit. Linqkit provides things to create predicate dynamically
Just install linqKit using packageManager, And use predicateBuilder to build predicate
var predicate = PredicateBuilder.True<Patient>();
predicate=predicate.And(...)
OR
predicate=predicate.Or(...)
And then use predicate in ur where clause
This way you can create Or (dynamically) as you would in dynamic SQL
You can get more details from here
https://www.c-sharpcorner.com/UploadFile/c42694/dynamic-query-in-linq-using-predicate-builder/
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.
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.
Hi this is my first question so apologies if it is really basic - I am very new to programming!!!
Using c# in MVC I am trying to select object which has a Date property from entitymodel context. This date then selects the relevant Weight object and so on to get my list of "Set" objects.
The code works and does what I want but would like some general guidance on how to make this code more concise. Here is the code:
public ActionResult showDiary(string datein)
{
LocalTestEntities1 dblists = new LocalTestEntities1();
DateTime date = Convert.ToDateTime(datein);
IEnumerable<ExerciseDiary> diary = from o in dblists.ExerciseDiaries where o.Date == date select o;
var mydiary = diary.ToList();
ExerciseDiary thediary = mydiary[0];
IQueryable<Weight> weights = from o in dblists.Weights where o.DiaryID == thediary.ID select o;
var selectedWeight = weights.ToList();
Weight weight = selectedWeight[0];
IEnumerable<Set> sets = from x in dblists.Sets where x.WeightId == weight.WeightID select x;
return View(sets);
}
It seems that I am taking too many steps here. I know that I am only returning one object to diary. Is there a way to get this object from dblists without sending to an IEnumerable?
Using the First() method will make things a little more concise:
public ActionResult showDiary(string datein)
{
using (LocalTestEntities1 dblists = new LocalTestEntities1())
{
DateTime date = Convert.ToDateTime(datein);
var thediary = (from o in dblists.ExerciseDiaries
where o.Date == date
select o).First();
var weight = (from o in dblists.Weights
where o.DiaryID == thediary.ID
select o).First();
var sets = (from x in dblists.Sets
where x.WeightId == weight.WeightID
select x).ToList();
}
return View(sets);
}
You should also wrap your LINQ to Entities data access in a using block so it's properly disposed of.
There's always many ways to do things, but... I think the easiest way would be to use First() since you are always just grabbing the first result in a list.
Another way to make it a little cleaner is to put your LINQ statements on multiple lines like I did for sets.
You can also use var, which some people like and others don't to have the compiler infer the type. I did this with sets below. I feel it cleans up the code a bit when you have large declarations with IEnumerable and generics.
public ActionResult showDiary(string datein)
{
LocalTestEntities1 dblists = new LocalTestEntities1();
DateTime date = Convert.ToDateTime(datein);
ExerciseDiary thediary = dblists.ExerciseDiaries.First(o => o.Date == date);
Weight weight = dblists.Weights.First(o.DiaryID == thediary.ID);
var sets = from x in dblists.Sets
where x.WeightId == weight.WeightID
select x;
return View(sets);
}
IMO this is easier to read than what you had in your answer above.
Be careful using First() because it will throw an exception if there are no records.
public ActionResult showDiary(string datein)
{
using( var dblists = new LocalTestEntities1())
{
var date = Convert.ToDateTime(datein);
var thediary = dblists.ExerciseDiaries.First(o => o.Date == date);
var weight = dblists.Weights.First(o => o.DiaryID ==thediary.ID);
var sets = dblists.Sets.Where(x => x.WeightId == weight.WeightID).AsEnumerable();
return View(sets);
}
}
Warning: If it's possible the data wont always be there. Use FirstOrDefault instead and check for null values.