Using a condition in LINQ - c#

How can I rewrite this using a condition in LINQ?
If the selectID = zero, I want this to run :
var products = from p in product.Table
orderby p.Name
where (p.stock == stockId)
select p;
If the selectID NOT zero, I want this to run :
var products = from p in product.Table
orderby p.Name
where (p.stock == stockId) &&
(p.Id == selectID)
select p;
This below works, but I have to use a "dummy" second condition (p.hidden == false)
for the ternary operator to work :
var products = from p in product.Table
orderby p.Name
where (p.stock == stockId) &&
(selectID != 0 ? p.Id == selectID : p.hidden == false)
select p;
Is there a way to get rid of (p.hidden == false) because it is not required in the logic and is just there to get the operator to work. thanks

You could use the same Id as the record as fallback value:
var products = from p in product.Table
orderby p.Name
where p.stock == stockId &&
p.Id == (selectID == 0 ? p.Id : selectID)
select p;
However, since that could lead to a less efficient query plan i would simply use an if-else:
var products = product.Table.Where(p => p.stock == stockId);
if(selectID != 0)
products = products.Where(p => p.Id == selectID);
products = products.OrderBy(p=> p.Name);

You could also write it like this:
var products = from p in product.Table
orderby p.Name
where (p.stock == stockId) &&
(p.Id == selectID || selectID == 0)
select p;
The || selectID == 0 just returns true if the ID isn't supplied and still allows the query to run as you intended. The link below was how I learned this simple trick.
http://www.sommarskog.se/dyn-search-2008.html

Related

Check if parameter value is null or not inside query

In my query I am getting records based on RoleId and LocationId, some times the user may not pass location in that case I want to remove that filter and get information from all locations.
Currently I am doing this way
if(loc > 0)
{
var myResult = (from x in CSDB.Allocations
join s in CSDB.Managers
on x.ManagerId equals s.Id
Where x.RoleId == 2 && s.LocationId == loc
select new
{
x.name,
x.Date
}).ToList();
}
else
{
var myResult = (from x in CSDB.Allocations
join s in CSDB.Managers
on x.ManagerId equals s.Id
Where x.RoleId == 2
select new
{
x.name,
x.Date
}).ToList();
}
I am seeing if I can check if loc is null or not inside the query instead of using if else.
You can do something like this:
Where x.RoleId == 2 && (loc == null || s.LocationId == loc)
Also, you can do smth like this.
Where x.RoleId == 2 && (loc?.Equals(s.LocationId) ?? true)
If loc just int I would prefer to use a little bit changed #Salah Akbari answer:
Where x.RoleId == 2 && (loc == 0 || s.LocationId == loc)
Simply extract your managers and filter them if needed. That way you can as well easily apply more filters and code readability isn't hurt.
var managers = CSDB.Managers.AsQueryable();
if(loc > 0)
managers = managers.Where(man => man.LocationId == loc);
var myResult = from allocation in CSDB.Allocations
join manager in managers on allocation.ManagerId equals manager.Id
where allocation.RoleId == 2
select new
{
allocation.name,
allocation.Date
};

Change SQL Query to LINQ, asp.net MVC

How to change this SQL query to LINQ? I've tried it several times, but it didn't work
SELECT Payment.ID, Payment.TotalGroupID, PaymentTrans.PaymentID, PaymentTrans.TotalGroupID as TotalGroupID1, PaymentTrans.TransferStatus
FROM PaymentTrans INNER JOIN Payment
ON (PaymentTrans.PaymentID = Payment.ID OR PaymentTrans.TotalGroupID = payment.TotalGroupID)
WHERE (PaymentTrans.TransferStatusis NULL OR (PaymentTrans.TransferStatus <> '01' and PaymentTrans.TransferStatus <> '02'))
and this is my try
var a= (from x in db.PaymentTransactions
join p in db.Payments
on
x.PaymentID equals p.ID
where x.TransferStatus== null || (x.TransferStatus!= "01" && x.TransferStatus!= "02")
select new { x, p }).ToList();
but it still wrong LINQ, because in my query I have 2 conditions in ON Clause. thanks
try this
var query = (from x in db.PaymentTransactions
join p in db.Payments
on x.PaymentID equals p.ID //main condition of join
where ((x.TransferStatus == null ||
(x.TransferStatus != "01" && x.TransferStatus!= "02")) //your `where` condition
|| x.TotalGroupID == p.TotalGroupID) //your second or join
select new {x,p})
.ToList();
The answers above filter on both conditions, they should filter one of the conditions according to the question (PaymentID or TotalPaymentID). You can either write two seperate queries and use a union or use a Cartesian product before filtering.
var result = (from paymentTransaction in db.PaymentTransactions
join payment in db.Payments on paymentTransaction.PaymentID equals payment.ID
where paymentTransaction.TransferStatus == null || (paymentTransaction.TransferStatus != "01" && paymentTransaction.TransferStatus != "02")
select new { paymentTransaction, payment }).Union
(from paymentTransaction in db.PaymentTransactions
join payment in db.Payments on paymentTransaction.TotalGroupID equals payment.TotalGroupID
where paymentTransaction.TransferStatus == null || (paymentTransaction.TransferStatus != "01" && paymentTransaction.TransferStatus != "02")
select new { paymentTransaction, payment });
var cartResult = from paymentTransaction in db.PaymentTransactions
from payment in db.Payments
where paymentTransaction.PaymentID == payment.ID || paymentTransaction.TotalGroupID == payment.TotalGroupID
where paymentTransaction.TransferStatus == null || (paymentTransaction.TransferStatus != "01" && paymentTransaction.TransferStatus != "02")
select new { paymentTransaction, payment };
You cannot add multiple ON in LINQ. the solution of your problem above can be solved like this.
Hint: just use multiple Where.
var result =
(
from trans in db.PaymentTransactions
join payment in db.payments
on trans.PaymentID equals payment.ID
where trans.TotalGroupID == payment.TotalGroupID
where x.TransferStatus== null || (x.TransferStatus!= "01" && x.TransferStatus!= "02")
select new
{
//your properties
}
).ToList();

Shortening loop to one QUERY in LINQ

Below is a piece of code that I do in a loop:
At the beginning, in the first query, I get a list of location IDs. The list can be long.
Ultimately, I need to find for which LocationId FamiliId > 0
I have it done in a loop but I would like to do it in one question. Is it possible and if so how?
var locationIds = context.TblUsersDistricts
.Where(d => d.UserId == userId && d.ValidityTo == null)
.Select(x => x.LocationId).ToList();
int familyId = 0;
foreach(var item in locationIds) {
familyId = (from I in context.TblInsuree
join F in imisContext.TblFamilies on I.FamilyId equals F.FamilyId
join V in imisContext.TblVillages on F.LocationId equals V.VillageId
join W in imisContext.TblWards on V.WardId equals W.WardId
join D in imisContext.TblDistricts on W.DistrictId equals D.DistrictId
where(I.Chfid == chfid &&
D.DistrictId == item &&
F.ValidityTo == null &&
I.ValidityTo == null &&
V.ValidityTo == null &&
W.ValidityTo == null &&
D.ValidityTo == null)
select F.FamilyId)
.FirstOrDefault();
if (familyId > 0) break;
};
It sounds like you want:
var familyId = (
from item in locationIds
from I in context.TblInsuree
// ... etc
&& D.ValidityTo == null)
select F.FamilyId)
.FirstOrDefault();
?

Where clause after String.Join in Linq to Entites

I have a Linq to Entites query where I have implemented the logic. But, I have done the query where clause performs after string join. BTW, I need to know how can I join the string first before doing the where filter. When I execute the query where clause after the string join, it takes so long to filter the records. Since my database have nearly 2 lakh sample records.
Here is my query what I am looking for:
// But the below query throws string join cannot be converted to store expression.
var NewBibContentsModel = (from x in db.BibContents
where (x.TagNo == "245" && string.Join(" ", x.NormValue) == aa.CurrentTitle) || ((x.TagNo == "020") || (x.TagNo == "022") && string.Join(" ", x.NormValue) == aa.CurrentISBN)
select new
{
BibId = x.BibId,
Title = (from a in db.BibContents where a.BibId == x.BibId && a.TagNo == "245" orderby a.Id ascending select a.NormValue),
Author = (from a in db.BibContents where a.BibId == x.BibId && splitted.Contains(a.TagNo) && a.NormValue != null select a.TagNo).FirstOrDefault(),
ISBN = (from a in db.BibContents where a.BibId == x.BibId && a.NormValue != null && (a.TagNo == "020" || a.TagNo == "022") orderby a.Id ascending select a.NormValue)
}).AsEnumerable().Select(x => new BibContentsModel
{
BibId = x.BibId,
Title = string.Join(" ", x.Title),
Author = string.Join(" ", (from a in db.BibContents where a.BibId == x.BibId && a.TagNo == x.Author orderby a.Id select a.NormValue)),
ISBN = string.Join(" ", x.ISBN),
RRId = aa.RRId
}).ToList();
Query with Where clause after string Join
// The below query takes so much of time to filter the records.
var NewBibContentsModel = (from x in db.BibContents
select new
{
BibId = x.BibId,
Title = (from a in db.BibContents where a.BibId == x.BibId && a.TagNo == "245" orderby a.Id ascending select a.NormValue),
//Tit = (from a in db.BibContents where a.BibId == line.BibId && a.TagNo == "245" && a.Sfld == "a" select a.NormValue).FirstOrDefault(),
Author = (from a in db.BibContents where a.BibId == x.BibId && splitted.Contains(a.TagNo) && a.NormValue != null select a.TagNo).FirstOrDefault(),
ISBN = (from a in db.BibContents where a.BibId == x.BibId && a.NormValue != null && (a.TagNo == "020" || a.TagNo == "022") orderby a.Id ascending select a.NormValue)
}).AsEnumerable().Select(x => new BibContentsModel
{
BibId = x.BibId,
Title = string.Join(" ", x.Title),
Author = string.Join(" ", (from a in db.BibContents where a.BibId == x.BibId && a.TagNo == x.Author orderby a.Id select a.NormValue)),
ISBN = string.Join(" ", x.ISBN),
RRId = aa.RRId
}).Where (x=> x.Title == aa.CurrentTitle || (x.ISBN == aa.CurrentISBN)).ToList();
Any help or suggestion to this problem will be appreciated.
Thanks,

linq to entities nested select fillout

I'm trying to return a result and a nested result in a linq to entities query.
Orders[] orderlist =
(from m in db.Orders.Include("OrderLines")
where
areas.Contains(m.Area)
&& m.Branch == branch
&& (m.OrderStatus == "1" || m.OrderStatus == "4")
&& m.SpecialInstrs == string.Empty
select m
HOW??---> m.OrderLines = m.OrderLines.Where(p => (p.LineType == "1" || p.LineType == "7") && p.MBomFlag != "C").ToArray()
).ToArray();
The problem is that the include returns all the FK'd OrderLines for each order when I really only want certain order lines.
How do I do this?
Orders and OrderList are both POCO entities generated by L2E and the poco entity generator.
You can manually join them:
Orders[] orderlist = (from m in db.Orders
join p in db.Orderlines
on p.OrderId = m.Id
where areas.Contains(m.Area)
&& m.Branch == branch
&& (m.OrderStatus == "1" || m.OrderStatus == "4")
&& m.SpecialInstrs == string.Empty
&& (p.LineType == "1" || p.LineType == "7")
&& p.MBomFlag != "C"
select m).ToArray();

Categories