Use Condition In Where Clause In Linq - c#

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))

Related

Can I have a nested OR statement within my Ternary If statement?

I am wondering if it is possible to turn this statement of code into a ternary if statement.
var placeHolder = await Source.EntityOrDefaultAsync<_Item>(item => item.CompanyID == order.CompanyID && item.ItemID == od.ItemID);
if (placeHolder.TaxedAllCountryRegions = true || placeHolder.TaxedFed == 1 && placeHolder.TaxedState == 1)
{
decimal.TryParse(placeHolder.HandlingFee, out decimal trueFee);
od.HandlingFee = trueFee * od.Quantity;
}
I tried formatting it like this- but don't think it quite works.
var placeHolder = await Source.EntityOrDefaultAsync<_Item>(item => item.CompanyID == order.CompanyID && item.ItemID == od.ItemID);
return (placeHolder.TaxedAllCountryRegions = true || placeHolder.TaxedFed == 1 && placeHolder.TaxedState == 1) ?
decimal.TryParse(placeHolder.HandlingFee, out decimal trueFee)
: false;
od.HandlingFee = trueFee * od.Quantity;
As canton7 already commented, you might want to use == true instead of = true. Probably
also the part after || must be embedded in parenthesis.
Apart from that, you want also assign the HandlingFee, so a conditional operator alone doesn't help. But why dont you use a bool variable?
bool computeHandlingFee = placeHolder.TaxedAllCountryRegions || (placeHolder.TaxedFed == 1 && placeHolder.TaxedState == 1);
if(computeHandlingFee && decimal.TryParse(placeHolder.HandlingFee, out decimal trueFee))
{
od.HandlingFee = trueFee * od.Quantity;
}
return computeHandlingFee;
Maybe you want to include the decimal.TryParse in the computeHandlingFee-logic.

LINQ with Contains return zero rows if i am passing empty string

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()) || ...

How to split string in c# linq?

I have this
from d in db.v_Report_CompanySearches
orderby d.InquiryLogID descending
where (mPersonName == null || d.AccountName.ToLower() == mPersonName || d.PersonName.ToLower() == mPersonName) &&
(mCompanyName == null || TagsContain(d.CompanySearchTerm, mCompanyName)) &&
d.CreateDT >= mFrom && d.CreateDT <= mTo
select (d);
and
private bool TagsContain(string terms, string val)
{
string[] tags = terms.ToLower().Split(';');
return tags.Contains(val.ToLower());
}
but it crashes with not supported error. I think it's because I'm using a custom function TagsContain. How can I do that function in linq without custom stuff?
Thanks
Id TagsContain isn't supported by EF and have an underlying SQL function, it will crash. That's exactly what is happening here.
This however, should work:
from d in db.v_Report_CompanySearches
orderby d.InquiryLogID descending
where (mPersonName == null || d.AccountName.ToLower() == mPersonName || d.PersonName.ToLower() == mPersonName) &&
(mCompanyName == null || d.CompanySearchTerm.Contains(mCompanyName)) &&
d.CreateDT >= mFrom && d.CreateDT <= mTo
select (d);
Provider not able convert your custom function the sql. And I afraid split is one of the functions which not supported for generating sql.
You can use it without .Split
var query =
db.v_Report_CompanySearches
.Where(report => report.CreateDT >= from)
.Where(report => report.CreateDT <= to);
if (String.IsNullOrEmpty(personName) == false)
{
query = query.Where(report => report.AccountName.ToLower() == personName ||
report.PersonName.ToLower() == personName);
}
if (String.IsNullOrEmpty(companyName) == false)
{
query = query.Where(report => report.CompanySearchTerm.StartsWith($"{companyName};") ||
report.CompanySearchTerm.Contains($";{companyName};")) ||
report.CompanySearchTerm.EndsWith($";{companyName}"))
}
var result = query.OrderByDescending(report => report.InquiryLogID).ToList();
What Fabio said is right. Split function of c# can not be converted into SQL query. So, you have one way here
Get all the values from DB into C# List object and then apply the split filter over it.
var myListObject = (from d in db.v_Report_CompanySearches
orderby d.InquiryLogID descending
where (mPersonName == null || d.AccountName.ToLower() == mPersonName || d.PersonName.ToLower() == mPersonName) &&
d.CreateDT >= mFrom && d.CreateDT <= mTo
select (d)).ToList();
Then
var afterFilterObject = myListObject.Where(d => (d.mCompanyName == null || TagsContain(d.CompanySearchTerm, mCompanyName))).ToList();
Method to be called
private bool TagsContain(string terms, string val)
{
string[] tags = terms.ToLower().Split(';');
return tags.Contains(val.ToLower());
}

Entity Framework Search functionality with Dynamic SQL WHERE clause

hi guys i was using Dynamic SQL for search queries where i used to attach WHERE & AND clause piece by piece and form a statement, i recently came to below alternate for this, and life was amazing
cool alternates of Dynamic WHERE-Clause
Select * From tblEmployees
where EmployeeName = Coalesce(#EmployeeName, EmployeeName) AND
Department = Coalesce(#Department, Department ) AND
Designation = Coalesce(#Designation, Designation) AND
JoiningDate >= Coalesce(#StartDate, JoiningDate) AND
JoiningDate <= Coalesce(#EndDate, JoiningDate) AND
Salary >= Coalesce(#Salary, Salary)
now the issue is since i implemented entity framework i need to achieve same with Linq queries. i have nullable Byte type and nullable boolean which i am currently unable to handle
just like Coalesce my stupid attempt was
&& (s.Floors == deal.Floors.HasValue ? null : s.Floors)
below code not matching any results
[HttpPost]
public ActionResult Results(Deal deal, bool exactMatch)
{
List<Deal> deals;
if (exactMatch)
{
deals = dataBase.Deals.Where(s =>
(s.OwnerName.Contains(deal.OwnerName) || s.OwnerName == null)
&& (s.Rooms == deal.Rooms || s.Rooms == null)
&& (s.BathRooms == deal.BathRooms || s.BathRooms == null)
&& (s.Floors == deal.Floors || s.Floors == null)
&& (s.Builtin == deal.Builtin || s.Builtin == null)
&& (s.Kitchens == deal.Kitchens || s.Kitchens == null)
&& (s.DoubleUnit == deal.DoubleUnit || s.DoubleUnit == null)
&& (s.Corner == deal.Corner || s.Corner == null)
&& (s.Remarks.Contains(deal.Remarks) || s.Remarks == null)
).ToList();
}
else
{
deals = dataBase.Deals.Where(s =>
(s.OwnerName.Contains(deal.OwnerName) || s.OwnerName == null)
|| (s.Rooms == deal.Rooms || s.Rooms == null)
|| (s.BathRooms == deal.BathRooms || s.BathRooms == null)
|| (s.Floors == deal.Floors || s.Floors == null)
|| (s.Builtin == deal.Builtin || s.Builtin == null)
|| (s.Kitchens == deal.Kitchens || s.Kitchens == null)
|| (s.DoubleUnit == deal.DoubleUnit || s.DoubleUnit == null)
|| (s.Corner == deal.Corner || s.Corner == null)
|| (s.Remarks.Contains(deal.Remarks) || s.Remarks == null)
).ToList();
}
return View(deals);
}
table has values like
id Bathroom Floors
1 1 2
2 1 4
3 2 6
4 3 1
i need results which has id 1 & 2
for instance in front end user want to only fill bathroom field with "1" and leave floor field empty
Not really the same. In your query your coalesce is on the parameter then taking the record value as the default if it is null. In your c# lambda you are checking if the parameter is the same as the table value and then checking if the table value is null but that omits the possibility of having a null value in the parameter.
Example
Sql
Department = Coalesce(#Department, Department )
would be
(s.Department == deal.Department || deal.Department == null)
not this which is what you have now
(s.Department == deal.Department || s.Department == null)
Edit
If you wanted to duplicate the COALESCE expression you have now you could write it this way although I am not sure if it would decrease efficiency / performance.
(s.Department == (deal.Department ?? s.Department))
You are testing whether the field in the table equals the 'deal' property or the field is null rather than doing this:
s.Remarks.Contains(deal.Remarks) || deal.Remarks == null
If you do this, it should be the equivalent query.
You can do this cumulatively too. For example with the exact match case you can do:
deals = dataBase.Deals;
if (deal.OwnerName != null)
deals = deals.Where(s => s.OwnerName.Contains(deal.OwnerName));
if (deal.Rooms != null)
deals = deals.Where(s => s.Rooms == deal.Rooms)
That can make the resulting query more efficient. There's a similar way to do this with the non exact match through using unions. I don't know the syntax off hand.

IQueryable with only optional parameters

I currently have the following method:
public List<Order> GetOrders(int profileId, string timeSpan, string workOrd, string partNo, bool includeDeleted)
{
DateTime startDate = DateTime.Now;
DateTime endDate = DateTime.Now;
string[] times = (!string.IsNullOrWhiteSpace(timeSpan)) ? timeSpan.Trim().Split('-') : new string[] { "", "" };
if (!string.IsNullOrWhiteSpace(times[0]) && !string.IsNullOrWhiteSpace(times[0]))
{
startDate = DateTime.Parse(times[0]).Date;
endDate = DateTime.Parse(times[1]).Date;
}
//New Real Query
IQueryable<Order_Travel> otQuery = _context.Order_Travels.Where(x =>
(profileId != 0 || x.Profile.ProfileID == profileId)
&& ((timeSpan == null || timeSpan.Trim() == "") || ((DbFunctions.TruncateTime(x.TimeRecieved) >= startDate)
&& (DbFunctions.TruncateTime(x.TimeRecieved) <= endDate)))
&& ((workOrd == null || workOrd.Trim() == "") || x.Order.WorkOrdNo == workOrd)
&& ((partNo == null ||partNo.Trim() == "") || x.Order.PartNo == partNo)
&& (!includeDeleted || x.Aborted == true));
//The results is now in order_travel. Under here binding them to a list of orders with only the respective orderTravels included.
List<Order> orders = new List<Order>();
List<Order_Travel> ots = otQuery.ToList();
foreach (Order_Travel ot in ots)
{
var OrderInList = orders.FirstOrDefault(X => X == ot.Order);
if (OrderInList == null)
{
orders.Add(ot.Order);
OrderInList = orders.FirstOrDefault(X => X == ot.Order);
OrderInList.OrderTravels.Clear();
OrderInList.OrderTravels.Add(ot);
}
else
{
OrderInList.OrderTravels.Add(ot);
}
}
return orders;
}
What I need it to do, is (as I've attempted) to make a call, finding all Order_Travel objects that match the paramters sent to it. If some (or all) are left blank, it takes everything, regardless of the values.
The code right now, does not return anything, if a blank search is made (a search that does not have any parameters), and I can not see what could be the issue. I have tried debugging it, but with no luck.
Any help would be greatly appreciated!
Thanks!
Filter one option at a time, instead of trying to put everything into a single expression:
IQueryable<T> query = all; // start with everything
if (IsPresent(option1))
{
query = query.Where(t => t.XXX == option1);
}
Example
IQueryable<Order_Travel> otQuery = _context.Order_Travels;
if (profileId != 0)
{
otQuery = otQuery.Where(x => x.Profile.ProfileID == profileId);
}
if (timeSpan != null && timeSpan.Trim() != "")
{
otQuery = otQuery.Where(x => DbFunctions.TruncateTime(x.TimeRecieved) >= startDate &&
DbFunctions.TruncateTime(x.TimeRecieved) <= endDate);
}
You will also find this easier to maintain than one huge expression.
Probably this part is your problem:
(profileId != 0 || x.Profile.ProfileID == profileId)
It should be
(profileId == 0 || x.Profile.ProfileID == profileId)
If your profile ID is 0, it will only find entries with x.Profile.ProfileID being 0. Probably there are no such entries.

Categories

Resources