I have an MVC5 project. On my page I have 4 checkboxes and a search button. When the button is clicked, an ajax call is triggered to call the function below:
[HttpPost]
public ActionResult GetOpenOrders(ProductionStatus pStatus)
{
List<vw_orders> orderList = new List<vw_orders>();
OrderRepository orderRepo = new OrderRepository();
// Get the total list of open orders
orderList = orderRepo.getAllByStatus("V");
// If not all values are 0, we have to filter
// (allZero is a private function that checks if all property values of pStatus are 0)
if(allZero(productieStatus) != true)
{
// Only use the properties of pStatus where
// the value is 1
// example: pStatus.A = 1, pStatus.B = 0, pStatus.C = 1
orderList = orderList.Where( p => if(pStatus.A == 1) p.a == pStatus.A || if(pStatus.B == 1) p.b == pStatus.B || if(pStatus.C == 1) p.c = pStatus.C);
}
// return some json of orderList.ToList()
}
How can I add the OR condition conditionally to my WHERE clause, thus only when value of
pStatus.property == 1 ?
replace
orderList = orderList.Where(p => if(pStatus.A == 1) p.a == pStatus.A || if(pStatus.B == 1) p.b == pStatus.B || if(pStatus.C == 1) p.c = pStatus.C)
with
orderList = orderList.Where(p => (pStatus.A == 1 && p.a == pStatus.A) ||
(pStatus.B == 1 && p.b == pStatus.B) ||
(pStatus.C == 1 && p.c == pStatus.C))
thus only when value of pStatus.property == 1
so p.a == pStatus.A and for pStatus.A == 1 need to be true to make this row part of the result.
If I understand your question correctly, you want to check the value of a property iff the respective property is set in the pStatus object.
This is simply, if pStatus.A == 1 then p.A == pStatus.A must be true. The problem with this statement is that we have to check the first part pStatus.A == 1, and then determine if we need to check the second part p.A == pStatus.A; which, we want to avoid having too many conditional checks within our linq statement since things can quickly get messy. So let's try to reduce what you are really checking for.
An easy way to show this is statement is as X=>Z(if X then Z), where X = pStatus.A == 1 and Z = p.A == pStatus.A. X=>Z is logically equivalent to ¬X v Z (not X or Z), because if X is not true we don't care what Z is and if Z is true then we don't care if X is true. In your situation, if pStatus.A != 1 then it doesn't matter what p.A is equal to, and if p.A == pStatus.A then it doesn't matter if pStatus.A == 1 or not because in either case the check will pass.
Now, if we substitute back in your checks for X and Z we get (!(pStatus.A == 1) || p.A == pStatus.A) which we can move the not inside the parenthesis and get (pStatus.A != 1 || p.A == pStatus.A).
If we substitute this equivilant statement in for the checks we get:
orderList = orderList.Where( p => (pStatus.A != 1 || p.A == pStatus.A) && (pStatus.B != 1 || p.B == pStatus.B) && (pStatus.C != 1 || p.C == pStatus.C);
We use && between the groups because we want each check to have to pass
Related
I have 4 checkboxes and based on which ones the user clicks on, I need to produce the LINQ statement. As mentioned below in the comment section, if I select just one checkbox, it works fine. If I select multiple checkboxes, it returns 0 results.
The 4 checkboxes are 1) "Item1" 2) "Item2" 3) "Item3" 4) "Item4".
This is what I have far:
var entity = _w_ItemRepository.GetMany(p => p.ID == id);
/* If I select just one item it works fine. If I select multiple items get 0 result */
entity = entity.Where
(p => (p.ItemType == 1 || !item1)
&& (p.ItemType == 2 || !item2)
&& (p.ItemType == 2 || !item3)
&& (p.ItemType == 3 || !item4)
);
I suspect the &&s need to be ||s. Consider if both item1 and item2 are true then you're essentially saying:
.Where(p => p.ItemType == 1 && p.ItemType == 2)
When the intent is probably:
.Where(p => p.ItemType == 1 || p.ItemType == 2)
(It also looks like there's a typo, you specify ItemType == 2 twice.)
Try:
entity = entity.Where
(p => (p.ItemType == 1 || !item1)
|| (p.ItemType == 2 || !item2)
|| (p.ItemType == 3 || !item3)
|| (p.ItemType == 4 || !item4)
);
Or I think this may be more clear, adding each clause if itemX is true:
entity = entity.Where
(p => (item1 && p.ItemType == 1)
|| (item2 && p.ItemType == 2)
|| (item3 && p.ItemType == 3)
|| (item4 && p.ItemType == 4)
);
My requirement is to make boolean value (IsPC=true) only if I found any value with IsCurrent = true from the list and second condition is to filter the list with G or W codes and third condition is to check the PCBNumber length ==15 with only one from the list.
How short can i able to reduce the below query using LINQ method syntax
below is my query
var CurrentQ= p.List.Where(x => x.IsConCurrent== true);
if (CurrentQ.Count() > 0)
{
var NCurrentQwithWorQ = p.List.Where(x => x.Codes == Codes.W|| x.Codes== Codes.Q).Count();
if (NCurrentQwithWorQ != null)
{
var PCBNumber = p.List.Where(x => x.PCBNumber .Length == 15).Count();
if (PCBNumber == 1)
{
isPC = true;
}
}
}
You can use all conditions in same query like below,
var PCBNumber= p.List.Where(x => x.IsConCurrent== true && (x.Codes == Codes.W|| x.Codes== Codes.Q) && x.PCBNumber.Length == 15);
if (PCBNumber !=null && PCBNumber.Count() == 1)
{
isPC = true;
}
I'm not trying to debug what you wrote, but isn't this really what you're looking for--that is, daisy-chaining your Where conditions?
var isPC = p.List.Where(x => x.IsConCurrent == true).Where(x => x.Codes == Codes.W || x.Codes == Codes.Q).Where(x => x.PCBNumber.Length == 15).Count() == 1;
Both solutions suggested above are correct.
p.List.Where(x => x.IsConCurrent== true && (x.Codes == Codes.W|| x.Codes== Codes.Q) && x.PCBNumber.Length == 15);
p.List.Where(x => x.IsConCurrent == true).Where(x => x.Codes == Codes.W || x.Codes == Codes.Q).Where(x => x.PCBNumber.Length == 15).Count()
Actually they are performed in the same way. The Where function does not force immediate iteration through the data source. Only when you execute the Count function, LINQ will process row by row and execute criterion by criterion to find out which values should be calculated.
I can only suggest you add the Take(2) operator after the where clause. In this case LINQ will stop after finding the first two rows that matches provided criterion and other rows will not be processed.
p.List.Where(x => x.IsConCurrent == true)
.Where(x => x.Codes == Codes.W || x.Codes == Codes.Q)
.Where(x => x.PCBNumber.Length == 15)
.Take(2).Count()
Id like to get all the parent that doesn't have in the signature table anything with
(Roleid 1 OR Roleid 2 OR Roleid 3) AND SignatureStatus IS <> NULL
RoleId - int: 0-13
SignatureStatus - bit: True, False, Null
I have this code but i still get the parent when i shouldn't and not getting it when i should..
result = Context.APP_AuthorityHasamaForm.Where(x =>
x.UpdateTypeId == (int)UpdateType.Unit && x.AuthorityNum == authorityUnit.AuthorityNum &&
x.InsertDate >= authorityUnit.FromDate && x.HasamaFormStatus == (int)Status.Valid &&
!(x.APP_SignatureAuthorityHasamaForm.Any(s =>
s.RoleId == (int)Role.EligibilityWorker1 || s.RoleId == (int)Role.DepartmentManager2 ||
s.RoleId == (int)Role.Treasurer3 && ((bool)s.SignatureStatus || !(bool)s.SignatureStatus)))).ToList();
How about changing it to be this?
!(x.APP_SignatureAuthorityHasamaForm.Any(s =>
(s.RoleId == (int)Role.EligibilityWorker1 || s.RoleId == (int)Role.DepartmentManager2 ||
s.RoleId == (int)Role.Treasurer3) && s.SignatureStatus.HasValue))).ToList();
I don't have your class structure but here goes few fixes , put brackets outside OR condition and use .HasValue for checking non null :
.Any(s =>
(s.RoleId == (int)Role.EligibilityWorker1 || s.RoleId == (int)Role.DepartmentManager2 ||
s.RoleId == (int)Role.Treasurer3) && ((bool)s.SignatureStatus.hasValue).ToList();
I have a query using Entity Framework. It has many different operands and I am confused with its priority. I am getting the wrong result. I need all records that IsPaid == true or IsPaid == null, also all records must be TypeId == 1 or TypeId == 2, also must be CityId == 1 and CategoryId == 2. For some reason it doesn't evaluate CityId and CategoryId.
What am I doing wrong? Thanks.
var list = db.Ads.Where (x =>
x.IsPaid == true || x.IsPaid == null &&
x.TypeId == 1 || x.TypeId == 2 &&
x.CityId == 1 && x.CategoryId == 2
).ToList();
The best way to solve this problem is using brackets.
You should always use them even if you know the binding prioritys, to increase readability of your code.
(x.IsPaid == true || x.IsPaid == null) && (x.TypeId == 1 || x.TypeId == 2) && x.CityId == 1 && x.CategoryId == 2
&& has a higher proirity than ||
So false && false || true would be translated to (false && false) || true => true
Sidenote as mentioned by #Joey:
Instead of (x.IsPaid == true || x.IsPaid == null) you can write (x.IsPaid != false).
Due to operator precedence, && binds higher than ||.
If you chain Where statements, it's more clear what happens:
var list = db.Ads
.Where(x => x.IsPaid == true || x.IsPaid == null)
.Where(x=> x.TypeId == 1 || x.TypeId == 2)
.Where(x=> x.CityId == 1)
.Where(x=> x.CategoryId == 2)
.ToList();
&& has a higher precedence than ||, just like in math. So, effectively your condition is the following:
x.IsPaid == true ||
x.IsPaid == null && x.TypeId == 1 ||
x.TypeId == 2 && x.CityId == 1 && x.CategoryId == 2
If any of those expressions on separate lines are true, the whole expression is true. You have to use parentheses to clarify here:
(x.IsPaid == true || x.IsPaid == null) &&
(x.TypeId == 1 || x.TypeId == 2) &&
x.CityId == 1 &&
x.CategoryId == 2
Try this:
var list = db.Ads.Where (
(x => x.IsPaid == true || x.IsPaid == null) &&
(x.TypeId == 1 || x.TypeId == 2) &&
(x.CityId == 1 && x.CategoryId == 2)
).ToList();
This question already has an answer here:
Conditional WHERE in LINQ
(1 answer)
Closed 9 years ago.
I need to write a conditional query in linq:
if field.val1 == 0:
var q = from field in cw.fields
select field
if field.val1 != 0 and field.val2 == 0:
var q = from field in cw.fields
where field.val1 == 1
select field
if field.val1 != 0 and field.val2 != 0:
var q = from field in cw.fields
where field.val1 == 1 and field.val2 == 1
select field
How can I do this?
Because your condition depends on the values your querying, you have to just extend your where clause with additional cases using ||:
var q = from field in cw.fields
where
(field.val1 == 0) ||
(field.val1 != 0 and field.val2 == 0 && field.val1 == 1) ||
(field.val1 != 0 and field.val2 != 0 && field.val1 == 1 and field.val2 == 1)
select field
#MarcinJuraszek's answer will work but let me give a different perspective.
First of all, ditch the sql style syntax. It gets in the way, obscures what is actually going on and is generally just a feel-good abstraction rather than one that will result in more communicative code. Let's rewrite things using lambda syntax
IEnumerable<string> getFields(SomeField field, YourDatabase cw) {
if(field.val1 == 0:)
return cw.fields.ToList();
if(field.val1 != 0 and field.val2 == 0)
return cw.fields.Where(f => f.val1 ==1).ToList();
if(field.val1 != 0 and field.val2 != 0)
return cw.fields.Where(f => f.val1 == 1 and f.val2 == 1).ToList();
}
note that the only way things differ is the lambda, and a lambda is an object, in this case, an Expression object! So you can use a very standard abstract factory pattern here
return cw.fields.Where(matchingCondition(field)).ToList();
//elsewhere...
Expression<Func<SomeField, bool>> matchingCondition(SomeField field) {
if(field.val1 == 0:) return f => true;
if(field.val1 != 0 and field.val2 == 0) return f => f.val1 == 1
if(field.val1 != 0 and field.val2 != 0) return f => f.val1 == 1 and f.val2 == 1;
throw new InvalidOperationException("No match to condition");
}