Use winform checkbox to linq query - c#

Hope I am asking this question in the right way.
I am trying to determine the most efficient way to use checkboxes to alter what is returned from my linq query without having to code for every possible combination.
As an example, I have three checkboxes on my winform that represent three columns that I am trying to query
[ ] Year
[ ] Make
[ ] Model
I am using a linq statement to determine the distinct combinations of year make and model through EF
var uniquecombos = cb.MakeModelYear.Where(i => i.Year != null && i.Make != null && i.Model != null).Distinct().ToList();
What I would like to do is use the checkboxes on my winform to drive which fields I include in my query.
So
[x] Year
[x] Make
[ ] Model
would yield
var uniquecombos = cb.MakeModelYear.Where(i => i.Year != null && i.Make != null).Distinct().ToList();
Is there a good way to modify the inputs of the query without having to account for every combination of checkboxes through if statements?
Thanks in advance!

Since you have separate properties you still ned to hceck each one - but you can account for each checkbox combination at the same time:
.Where(i => (
(!cbxYear.Checked || i.Year != null) &&
(!cbxMake.Checked || i.Make != null) &&
(!cbxModel.Checked || i.Model != null)
)

You can do something like this :
var query = cb.MakeModelYear;
if (chkYear.Checked)
query = query.Where(i => i.Year != null);
if (chkMake.Checked)
query = query.Where(i => i.Make != null);
if (chkModel.Checked)
query = query.Where(i => i.Model != null);
var uniquecombos = query.Distinct().ToList();

Related

how to generate where condition without multiple if condition using linq query

I have 3 search textbox values. i need to check string.isnullorEmpty for each variable and have to compare with the linq query.
My Text Values:
Manufacturer
Project Code
PartNo
Conditions:
if i search any one of the above i should get the result
If i enter 3 box values i should get the result
If i enter any 2 then i should get result.
My code as follows
if (!string.IsNullOrEmpty(manufacturer))
{
var filteredResult = _entity.MaterialMasters.Where(x => x.Manufacturer == manufacturer);
}
if (!string.IsNullOrEmpty(projectcode))
{
var filteredResult = _entity.MaterialMasters.Where(x => x.ProjectCode== projectcode);
}
if (!string.IsNullOrEmpty(part))
{
var filteredResult = _entity.MaterialMasters.Where(x => x.Part== part);
}
To avoid multiple conditions how to make dynamic where clause for this? Please find out the solution for this..
He wants to get rid of the if statements and write this all as a linq query. I think you want something like this
.Where(
s =>
(string.IsNullOrEmpty(manufacturer) | (s.Manufacturer == manufacturer)) &&
(string.IsNullOrEmpty(projectcode) | (s.ProjectCode == projectcode)) &&
(string.IsNullOrEmpty(part) | (s.Part== part))
).ToList();
You can just tag on multiple Where clauses
var filteredResult = _entity.MaterialMasters;
if (!string.IsNullOrEmpty(manufacturer))
filteredResult = filteredResult.Where(x => x.Manufacturer == manufacturer);
}
if (!string.IsNullOrEmpty(projectcode))
filteredResult = filteredResult.Where(x => x.ProjectCode == projectcode);
}
if (!string.IsNullOrEmpty(part))
filteredResult = filteredResult.Where(x => x.Part == part);
}
They will work cumulatively, meaning that you can supply 1, 2 or 3 of the parameters and you'll get the appropriate results.
var filteredResult =
_entity.Where(
ent =>
(!string.IsNullOrEmpty(manufacturer) && ent.Manufacturer == manufacturer)
|| (!string.IsNullOrEmpty(projectcode) && ent.ProjectCode == projectcode)
|| (!string.IsNullOrEmpty(part) && ent.Part == part));
This will get you any result for manufacturer, projectCode and part in one place.

C# IQueryable not working

I have a findAll function that gets all the records from a Contacts table in the Database and then filters them depending on which values the user selected in the search form. The results are filtered one filter at the time.
IQueryable<Contact> resultContacts = db.Contacts;
if(request['Name'] != "")
{
resultContacts = resultContacts.Where(a => a.Name.Contains(Name));
}
if(request['Phone'] != "")
{
resultContacts = resultContacts.Where(a => a.Phone.Equals(Phone));
}
if(request['Company'] != "")
{
resultContacts = resultContacts.Where(a => a.Company.Contains(Company));
}
return resultContacts;
The problem is that now this is not working. The resultContacts.Where inside each if is resetting to the original resultContacts I had on the first line for some reason. For instance: when I debug, the changes apply inside the 1st if (I end up with 10 out of 100 records), but when I go into the 2nd if, the code is querying the original resultContacts, not the 10 I had as a result of the first if.
This worked fine for over a year until 2 weeks ago. I don't know if something changed on my code... if I added a reference or something that make this change.
Any idea why?
Thank you!
var results = db.Contacts
.Where(a => request["Company"] == String.Empty || a.Company.Contains(Company))
.And(a => request["Phone"] == String.Empty || a.Phone.Equals(Phone))
.And(a => request["Name"] == String.Empty || a.Name.Contains(Name)));

comparing 2 lists of objects and return changes in the new list

I have a web app that gives users a feature to update (no delete or add) multiple records on the same page. As users submit changes, I pull the original list from the database and use linq to compare it to the updated list. Any changed records will be put on a new list and send to database for update.
Below is my code to compare. As I debug, I can see the 2 lists are different but the code returns the Differences with comparer = null, first = null, second = null. Can you guys spot the bug?
var Differences = OriginalList.Where(x => !NewList.Any(x1 => x1.ServiceName == x.ServiceName
&& x1.ServiceDescription == x.ServiceDescription
&& x1.ServiceURL == x.ServiceURL
&& x1.OrderIndex == x.OrderIndex
&& x1.GroupID == x.GroupID
&& x1.Active == x.Active))
.Union(NewList.Where(x => !OriginalList.Any(x1 => x1.ServiceName == x.ServiceName
&& x1.ServiceDescription == x.ServiceDescription
&& x1.ServiceURL == x.ServiceURL
&& x1.OrderIndex == x.OrderIndex
&& x1.GroupID == x.GroupID
&& x1.Active == x.Active)));
return Differences;
You are probably looking for Linq's Except method.
https://msdn.microsoft.com/library/bb300779(v=vs.100).aspx
You'll need to define how to compare for equality of your "x1" object. Probably the easiest way to do that is to override Equals():
https://msdn.microsoft.com/en-us/library/ms173147(v=vs.80).aspx
Then to get the difference, you simply do:
var Differences = OriginalList.Except(NewList);

MongoDB Select with QueryBuilder

i'm trying to select values from my database, but currently i'm unable to to it and although i know its the fact that the method doesnt except the QueryBuilder class as a parameter, i dont know what to do about it. I only found solutions for querys with one parameter or all parameters are not null. In my case i've a List with ID, and 4 parameters which dont have to be passed to the function so they could be null.
My current code looks like this.
collection = db.GetCollection<Datapoint>("test");
var query = new QueryBuilder<Datapoint>();
var queryattributes = new List<IMongoQuery>();
var ids = new List<IMongoQuery>();
// Add all Attributes if there
if (fromdate != null)
{
BsonDateTime from = BsonDateTime.Create(fromdate);
queryattributes.Add(Query.GTE("UTCTimestamp", from));
}
if (to != null)
{
BsonDateTime bto = BsonDateTime.Create(to);
queryattributes.Add(Query.LTE("UTCTimestamp", bto));
}
if (evId != null)
{
queryattributes.Add(Query.EQ("EvId", evId));
}
if (evType != null)
{
queryattributes.Add(Query.EQ("EvType", evType));
}
// Add all ID's
Parallel.ForEach(idList, data =>
{
lock (query)
{
ids.Add(Query.EQ("CId", data));
}
});
// But everything in the Query
query.Or(ids);
// Add Queryattributes if there
if (queryattributes.Count > 0)
{
query.And(queryattributes);
}
var result = collection.FindAs<Datapoint>(query);
I'm trying to do it without Linq, since i found countless of test, which say that linq is much much slower, and since i want to run it as an Databasetest, i kinda need the performace to execute alot of querys.
The Linq query looks like this
var query2 =
from e in collection.AsQueryable<Datapoint>()
where idList.Contains(e.CId)
&& (evtId == null || e.EvId == evId)
&& (evType == null || e.EvType == evType.Value)
&& (fromdate == null || Query.GTE("UtcTimestamp", BsonDateTime.Create(fromdate)).Inject())
&& (to == null || Query.LT("UtcTimestamp", BsonDateTime.Create(to)).Inject())
select e;
The QueryBuilder doesn't save a query inside it. You use it to generate a IMongoQuery and then use that query to actually query the database.
It seems the end of your code should look like this;
// But everything in the Query
IMongoQuery mongoQuery = query.Or(ids);
// Add Queryattributes if there
if (queryattributes.Count > 0)
{
mongoQuery = query.And(queryattributes);
}
var result = collection.FindAs<Datapoint>(mongoQuery);

Only do Where condition if a value is passed in

I have the following LINQ statement that does on where on the date and a LabID.
I'm passing in a list of LABS and a date, however they are not required, and I could potentially only pass in a date, and no lab, in which case I'd like to get results for all labs for that particular lab.
here is what I have now:
List<dExp> lstDatExp = (from l in ctx.dExp.Include("datLab")
where values.Contains(l.datL.Lab_ID)
&& l.reportingPeriod == reportingPeriod
select l).ToList<dExp>();
But this breaks if the value getting passed in is not there. How do I change this to make sure both of my where statements are optional?
With IQueryable you can simply add conditions in steps:
int? reportingPeriod = ...;
IQueryable<dExp> resultsQuery = // don't use `var` here.
ctx.dExp.Include("datLab");
if (values != null)
resultsQuery = resultsQuery.Where(exp => values.Contains(exp.datL.Lab_ID));
if (reportingPeriod.Hasvalue)
resultsQuery = resultsQuery.Where(exp => exp.reportingPeriod == reportingPeriod.Value);
// additional .Where(), .OrderBy(), .Take(), .Skip() and .Select()
// The SQL query is made and executed on the line below
// inspect the string value in the debugger
List<dExp> results = resultsQuery.ToList();
Here are two ways to do that.
But first, please don't use a single lowercase l as an identifier. It is way too easy to confuse it with the number 1. More generally, stp using abbrevs in yr cde, it mks it hrdr to rd.
First technique:
var query = from lab in ctx.dExp.Include("datLab")
where values == null || values.Contains(lab.datL.Lab_ID)
where reportingPeriod == null || lab.reportingPeriod == reportingPeriod
select lab;
var list = query.ToList<dExp>();
Second technique:
IEnumerable<dExp> query = ctx.dExp.Include("datLab");
if (values != null)
query = query.Where(lab=>values.Contains(lab.datL.Lab_ID));
if (reportingPeriod != null)
query = query.Where(lab=>lab.reportingPeriod == reportingPeriod);
var list = query.ToList<dExp>();
What we do is something like (l.reportingPeriod == reportingPeriod || reportingPeriod == null) So you check to see if the parameter is its default meaning it hasnt been used or if there is something there check it against the database.
You need to check if your values are null before doing the query, and if they are, don't do the extra condition.
List<dExp> lstDatExp =
(from l in ctx.dExp.Include("datLab")
where
(values == null || values.Contains(l.datL.Lab_ID)) &&
(reportingPeriod == null || l.reportingPeriod == reportingPeriod)
select l).ToList<dExp>();
This way if values or reportingPeriod are null they are essentially optional.

Categories

Resources