I have the following bool Variables:
public bool bCompanyID { get; set; }
public bool bTaxCode { get; set; }
public bool bAccountCode { get; set; }
Depending on which ones are set to true I set the LINQ expression (this is an example where all three are true:
System.Collections.Generic.IEnumerable<IP_DataRow> items = null;
items = _vm.Result_Error.Where(n => n.CompanyID == SelectedItem.CompanyID && n.TaxCode == SelectedItem.TaxCode && n.AccountCode == SelectedItem.AccountCode);
What I would like to do (rather than using multiple if statements) is to create this expression dynamically based on the user input.
Is something like this possible, or I simply have to use if statements?
EDIT:
Here is what came to my mind:
items = _vm.Result_Error.Where(n => ((bCompanyID) ? (n.CompanyID == SelectedItem.CompanyID) : true) &&
((bTaxCode) ? (n.TaxCode == SelectedItem.TaxCode) : true) &&
((bAccountCode) ? (n.AccountCode == SelectedItem.AccountCode) : true));
Can I use the above mentioned expression?
Well you can combine then into one using something like this:
System.Collections.Generic.IEnumerable<IP_DataRow> items = null;
items = _vm.Result_Error.Where(n => (!bCompanyID || n.CompanyID == SelectedItem.CompanyID)
&& (!bTaxCode || n.TaxCode == SelectedItem.TaxCode)
&& (!bAccountCode || n.AccountCode == SelectedItem.AccountCode));
but an if statement might be cleaner, especially since you can attach multiple where clauses to an existing query:
items = _vm.Result_Error.AsEnumerable();
if(bCompanyID)
items = items.Where(n => n.CompanyID == SelectedItem.CompanyID);
if(bTaxCode)
items = items.Where(n => n.TaxCode == SelectedItem.TaxCode);
if(bAccountCode)
items = items.Where(n =>n.AccountCode == SelectedItem.AccountCode);
You can combine some conditions with if statements:
var items = _vm.Result.Errors;
if (bCompanyID)
items = items.Where(n => n.CompanyID == SelectedItem.CompanyID);
if (bTaxCode)
items = items.Where(n => n.TaxCode == SelectedItem.TaxCode);
. . .
You can also create single LINQ expression that (as I think) is not so effective:
var items = from item in _vm.Result.Errors
where !bCompanyID || item.CompanyID == SelectedItem.CompanyID
where !bTaxCode || item.TaxCode == SelectedItem.TaxCode
. . .
select item;
In the second case the lazy evaluating of && and || operators is used, so if bCompanyID is false, then right conditions will not evaluating.
Related
i don't know how to handle this in LINQ
simply i have a searchKey in which i am passing user enter data and it return with rows. but if i am not passing any searchkey it not given any data. i dont want to add contains if searchkey is empty :(
var AppointmentList = (from app in Con.ios_Appointment
where (app.IS_DELETED == false && app.CLINICIANID == appReq.id
&& app.FNAME.Contains(appReq.searchKey.Trim()) || app.LNAME.Contains(appReq.searchKey.Trim()) || app.ADDRESS.Contains(appReq.searchKey.Trim())
)
orderby app.DATE descending
select new
{
app.ID,
app.FNAME,
app.LNAME,
app.DATE,
app.LONGITUDE,
app.LATITUDE,
app.ADDRESS,
app.STATUS,
app.START_TIME
}).Skip(skipRecord).Take(Convert.ToInt32(record)).ToList();
I suggest you use method syntax to easily build the query up programatically:
var query = Con.ios_Appointment.Where(app => !app.IS_DELETED && app.CLINICIANID == appReq.id);
var search = appReq.searchKey.Trim();
if (search != "")
{
query = query.Where(app => app.FNAME.Contains(search) ||
app.LNAME.Contains(search) ||
app.ADDRESS.Contains(search));
}
var appointments = query
.OrderByDescending(app => app.DATE)
.Select(app => new
{
app.ID,
app.FNAME,
app.LNAME,
app.DATE,
app.LONGITUDE,
app.LATITUDE,
app.ADDRESS,
app.STATUS,
app.START_TIME
})
.Skip(skipRecord)
.Take(Convert.ToInt32(record))
.ToList();
You need to use string.IsNullOrWhiteSpace method:
where (app.IS_DELETED == false &&
app.CLINICIANID == appReq.id &&
(string.IsNullOrWhiteSpace(appReq.searchKey) ||
app.FNAME.Contains(appReq.searchKey.is Trim()) || ...
Illustration of database (actual column and table name is different)
EmployeeeID IsSicked IsRetired IsHoliday
1 false false true
2 true false true
3 true true true
4 false false false
What problem am I having?
I have a checkbox for IsSicked, IsRetired and IsHoliday in my application, which allow user to check multiple selection and submit.
The system will return list of employee from database based on the selection of user. For example, when user tick IsSicked and IsRetired, system will return list of user who is sicked and is retired from database.
Based on below code, I need to write 2^3 = 8 possibilities to get the result.
As the column expand to n columns(exluding employeeID column), I will need to write 2^n if else statement to get the query.
If there are 10 column (10 checkboxes selection), then i need to write 2^10 = 1024 if else statement
It seems to me that this supposed to be quite a common problem faced by developers, unfortunately i can't find a good solution to this online
Expectation of solution
Generic combination of C# code and/or LINQ query that no need hard code the logic as below if(...) else if (...)
var employee = db.Employee.AsQueryable():
if(model.IsSicked == true)
{
employee.Where(z => z.IsSicked == true)
}
else if(model.IsRetired == true)
{
employee.Where(z => z.IsRetired == true)
}
...
...
else if(model.IsSicked == true && model.IsRetired == true)
{
employee.Where(z => z.IsSick == true || z.IsRetired == true)
}
else if (model.IsSicked == true && model.IsRetired == true && model.IsHoliday == true)
{
employee.Where(z => z.IsSick == true || z.IsRetired == true || z.IsHoliday == true)
}
Why not use a enum with [Flags]:
[Flags]
public enum EmployeeStatus
{
None = 0,
Sick = 1,
Retired = 2,
Holiday = 4
}
In your database you can store this as an integer.
Your model becomes similar to
public class Employee
{
public int Id { get; set; }
public EmployeeStatus Status { get; set }
}
then LINQ queries become similar to:
employee.Where(z => z.Status == EmployeeStatus.Sick)
Because of using [Flags] you can do the following for multiple states, e.g. sick and retired:
employee.Where(z => z.Status == (EmpoyeeStatus.Sick | EmployeeStatus.Retired))
Please note that | is the boolean OR which translates in the following:
EmpoyeeStatus.Sick | EmployeeStatus.Retired
= 1 | 2
= b01 | b10
= b11
= 3
so effectively works as "and" in our logic.
You can use library called LINQKit and use its PredicateBuilder to create predicate with dynamic ORs.
var employee = db.Employee.AsQueryable():
var predicate = PredicateBuilder.False<Employee>();
if (model.IsSicked == true)
predicate = predicate.Or(p => p.IsSick == model.IsSick);
if (model.IsRetired == true)
predicate = predicate.Or(p => p.IsRetired == model.IsRetired);
if (model.IsHoliday == true)
predicate = predicate.Or(p => p.IsHoliday == model.IsHoliday);
var result = employee.AsExpandable().Where(c => predicate.Invoke(c)).ToList()
You can build up your Where predicate like this:
var employee = db.Employee.AsQueryable():
if(model.IsSicked == true)
employee = employee.Where(z => z.IsSicked == true)
if(model.IsRetired == true)
employee = employee.Where(z => z.IsRetired == true)
if (model.IsHoliday == true)
employee = employee.Where(z => z.IsHoliday == true)
Alternatively, you could do this:
employee.Where(z => (z.IsSicked || !model.IsSicked) &&
(z.IsRetired || !model.IsRetired) &&
(z.IsHoliday || !model.IsHoliday))
I'm trying to write a linq query that uses an if statement.
In the code below I'm searching for matches of
n.SAU_ID = sau.SAUID where
ReportingPeriod column contains "Oct1" then
FiscalYear - aprYearDiff = sau.SAUYearCode.
Else
FiscalYear - octYearDiff = sau.SAUYearCode.
My code is only giving matches for the SAUID and "Oct1".
What code is needed to implement theese statements?
int FiscalYear = 2014;
List<String> addtowns = new List<string>();
List<Stage_Reorg> reorg = _entities.Stage_Reorg.ToList();
int aprYearDiff = 2;
int octYearDiff = 1;
foreach (var sau in reorg)
{
addtowns.AddRange(_entities.Stage_EPSSubsidySADCSDTown
.Where(n => n.SAU_ID == sau.SAUID
&& (n.ReportingPeriod == "Oct1"
? (FiscalYear - aprYearDiff) == sau.SAUYearCode
: (FiscalYear - octYearDiff) == sau.SAUYearCode))
.Select(n => n.TownCode ));
}
This is a bad idea anyway. Transform the condition to
(n.ReportingPeriod == "Oct1" && (FiscalYear - aprYearDiff) == sau.SAUYearCode)
|| (n.ReportingPeriod != "Oct1" && (FiscalYear - octYearDiff) == sau.SAUYearCode)
Here is a possible way but this probably won't work with EF. You will need to load all records into memory then perform the filtering:
addtowns.AddRange(_entities.Stage_EPSSubsidySADCSDTown
.Where(n => {
bool b = n.ReportingPeriod == "Oct1"
? (FiscalYear - aprYearDiff) == sau.SAUYearCode
: (FiscalYear - octYearDiff) == sau.SAUYearCode);
return b && n.SAU_ID == sau.SAUID;
}).Select(n => n.TownCode ))
I have a search form which i want to use to search a database for data. The searchbox has 4 checkboxes and 1 textfield. The problem is how do i build the linq query considering i dont know beforehand what textboxes the user will check for filtering the search. What i have so far is:
[HttpPost]
public ActionResult search(string ulv, string bjorn, string jerv, string gaupe)
{
var query = (from o in db.observasjonene select o);
if (ulv != null)
{
query = query.Where(o => o.art == ulv);
}
if (bjorn != null)
{
query = query.Where(o => o.art == bjorn);
}
if (jerv != null)
{
query = query.Where(o => o.art == jerv);
}
if (gaupe != null)
{
query = query.Where(o => o.art == gaupe);
}
IEnumerable ls = query.ToList();
return Json(ls, JsonRequestBehavior.AllowGet);
}
The problem with the "where" clause is that if a condition is true, it overwrites the results from the earlier condition. I guess i need an "or" statement or something..
If I have understood your question correctly, you want to check if art equals to any of provided values. You can combine those values into collection and check if collection contains art value:
var values = new [] { ulv, bjorn, jerv, game }.Where(v => v != null);
var query = from o in db.observasjonene
where values.Contains(o.art)
select o;
EF translates Contains into SQL IN operator.
I'm using two approaches in this case:
Build dynamic query:
var q = DB.Invoices.AsQueryable();
if (isPresented != null)
q = q.Where(iv => iv.IsPresented == isPresented);
if (ID != null)
q = q.Where(iv => iv.ID == ID.Value);
...........................
return from iv in q
orderby iv.DueDate descending
select iv;
Use Union to combine search results:
var q1 = db.FeeInvoice.Where(fi => [QUERY1]));
if (isPresented != null)
{
var q2 = db.FeeInvoice.Where(fi =>[QUERY2]));
q1.Union(q2);
}
if (ID != null)
{
var q3 = db.FeeInvoice.Where(fi =>[QUERY3]);
q1.Union(q3);
}
...........................
You are comparing all the parameters value to single column in the query ie. art (see you have written same column name in each where condition) . I'm not sure why are you doing so? you can simply take single parameter which compare the value like this
public ActionResult search(string value)
{
query = query.Where(o => o.art == value);
}
or if it is by mistake and you want to apply where condition along with multiple column then you can try something like this
query=query.Where(o => (o.art == ulv || ulv == string.Empty) && (o => o.bjorn == bjorn || bjorn=string.empty) && (o.jerv == jerv || jerv == string.Empty) && (o.gaupe == gaupe || gaupe == string.Empty));
Note: I assume your column name as your parameters name.
How Can I use Condition in Where Clause?
user can select section,product and model from list and see the result.
i add an item See All in all the filed,if user select See All,he can see all product in all section.so i want to write
a query that check for value if every property equal -1 dot bring in where condition.
//My Model
struct Model
{
public int SectionCode{get;set;}
public int ProductCode{get;set;}
public int ModelCode{get;set;}
}
var query=DBContext.Model.Where(data=>data.ModelCode==_ModelCode//if ModelCode!=-1
&& ProductCode==_ProductCode//if ProductCode!=-1
&& SectionCode==_SectionCode//if SectionCode!=-1 )
I know that i can write it with some if but i have to check a lot of condition.so i want to know, how can i write if in where Clause?
Just don't add a where clause if you don't need it, i.e:
IQueryable<Model> query = DBContext.Model;
if(_ModelCode != -1)
{
query = query.Where(data=>data.ModelCode==_ModelCode);
}
if(_ProductCode!= -1)
{
query = query.Where(data=>data.ProductCode==_ProductCode);
}
if(_SectionCode!= -1)
{
query = query.Where(data=>data.SectionCode==_SectionCode);
}
Try this :
var query=DBContext.Model.Where(data => (ModelCode == -1 || data.ModelCode == _ModelCode)
&& (ProductCode == -1 || ProductCode == _ProductCode)
&& (SectionCode == -1 || SectionCode == _SectionCode)
You could achieve this using logical operators:
var query = DBContext.Model.Where(data =>
(_ModelCode == -1 || data.ModelCode == _ModelCode)
&& (_ProductCode == -1 || data.ProductCode == _ProductCode)
&& (_SectionCode == -1 || data.SectionCode == _SectionCode))