I am trying to query a database with multiple where clauses.
IQueryable<string> statusQuery = from m in _context.Flight
where m.Aircraft_Type == aircraftType
&& m.Identification_Registration == registration
&& m.Destination_Airport_City == to1
&& m.DepartureDate.ToString("yyyy-MM-dd") == date1
&& m.Origin_Airport_City == from1
orderby m.Status_Text
select m.Status_Text;
This code is working, but only if I am able to supply a value to each variable.
How can I use this with a check if e.g registration == null => do not check use
&& m.Identification_Registration == registration
if(...) doesn't work here.
You can emulate this behavior using logical operators:
IQueryable<string> statusQuery =
from m in _context.Flight
where m.Aircraft_Type == aircraftType
&& (registration == null || m.Identification_Registration == registration)
&& m.Destination_Airport_City == to1
&& m.DepartureDate.ToString("yyyy-MM-dd") == date1
&& m.Origin_Airport_City == from1
orderby m.Status_Text
select m.Status_Text;
Related
I'm trying to do a conditional OrderBy but it's having no effect. The List outputs the same with default ordering.
I've tried both approaches suggested in this question Conditional "orderby" sort order in LINQ
var query = _context.Groups
.Where(gr => gr.Status != ((sbyte)ActiveStatus.DELETED)
&& gr.OrganisationId == user.OrganisationId
&& (search != null && gr.Name != null ? (gr.Name.Contains(search)) : true == true)
)
.Select(GroupReportModel.Projection);
if(!pager.Sort.HasValue || pager.Sort.Value == ((int)Sort.MODIFIED))
query.OrderByDescending(gr => gr.Created.Date);
if(pager.Sort.Value == ((int)Sort.NAME))
query.OrderByDescending(gr => gr.Name);
pager.TotalRecords = query.Count();
var list = query.Skip(pager.PageCount != null ? pager.PageCount.Value * (pager.Page.Value) : 0)
.Take(pager.PageCount != null ? pager.PageCount.Value : 0)
.ToList();
LINQ methods do not mutate the query object, they return a new one, you need to reassign it:
if(!pager.Sort.HasValue || pager.Sort.Value == ((int)Sort.MODIFIED))
query = query.OrderByDescending(gr => gr.Created.Date);
if(pager.Sort.Value == ((int)Sort.NAME))
query = query.OrderByDescending(gr => gr.Name);
....
I want to retrieve some data from database based on some condition, for this I'm using LINQ. But problem is that I don't know how to write LINQ when some condition may be null.
from x in _db.AirWorkOrder
join c in _db.Clients on x.ClientId equals c.Id
where x.CreatedOn >= model.StartDate && x.CreatedOn <= model.EndDate && x.ClientId == model.ClientId && x.Type == model.Type && x.WorkOrderStatus == model.Status
select new DateWisedReportItemModel
I want if the clientID, type, status have null value then it will take all the values saved in the DB. and if there are some values provided in it, then it will work according to the condition.
I presume you're asking how to wildcard things that are null. You need to make the particular clause true if your model value is null. You could do this by saying things like:
(dbcolumn == modelvalue || modelvalue == null) && ...
Or like
(dbcolumn == modelvalue == null ? dbvalue : modelvalue) && ...
Or like
(dbcolumn == modelvalue ?? dbvalue)
For example:
from x in _db.AirWorkOrder
join c in _db.Clients on x.ClientId equals c.Id
where
(x.CreatedOn >= model.StartDate ?? x.CreatedOn) &&
(x.CreatedOn <= model.EndDate == null ? x.CreatedOn : model.EndDate) &&
(x.ClientId == model.ClientId || model.ClientId == null) &&
...
I prefer the first as it is the most easy to understand. Also note carefully that it is the only one that will return the row if the row value in the db is null, because to a database null is never equal to null
I want if there is no condition given in ClientId, type and status then only date(this is mandatory) filter will apply, and if there is condition in these only then these(clientId, type and status) conditions will work
It might be most simple, in terms of code readability to do like:
var baseQuery = from x in _db.AirWorkOrder
join c in _db.Clients on x.ClientId equals c.Id
IEnumerable<...> result;
if(model.ClientId == null && model.Type == null && model.Status == null){
//search on date only
result = baseQuery.Where(x.CreatedOn >= model.StartDate && x.CreatedOn <= model.EndDate);
} else {
//search on no null client/type/status only
result = baseQuery.Where(x =>
(x.ClientId == model.ClientId || model.ClientId == null) &&
(x.Type == model.Type || model.Type == null) &&
(x.WorkOrderStatus == model.Status || model.Status == null);
}
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());
}
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.
I am maintaining a project and have come across some code which I can't understand. LINQ query:
var toDraw = from tile in testArr.AsEnumerable()
where tile.Item_Business_Unit != null ?
((tile.Ending_Date >= DateTime.Now || tile.Ending_Date == DateTime.MinValue) &&
((tile.Sales_Code == null) || (tile.Sales_Code.ToString() == customerNumber) ||
(tile.Sales_Code.ToString() == cpg)) && (tile.Unit_Price != 0)) :
((tile.Ending_Date >= DateTime.Now || tile.Ending_Date == DateTime.MinValue) &&
((tile.Sales_Code == null) || (tile.Sales_Code.ToString() == customerNumber) ||
(tile.Sales_Code.ToString() == cpg)) && (tile.Unit_Price != 0))
select tile;
From what I understand, from an array a tile is being selected which has the following criteria:
Ending date can be datetime.now or datetime.minvalue
Sales code can be null or can be equal to customer no or cpg
Unit price should be greater than 0
But I am not understanding why there is a conditional expression after tile.Item_Business_Unit since both of the conditions perform the same thing. So will the item be selected even if it has a null business unit? And does this work different from normal if/else operations?
Any suggestions would be very appreciated.
Are you being thrown by the shortcut notation?
x = (test_case) ? (true_part) : (false_part);
If test_case evaluates to true, you would have
Whereas if test_case evaluates to false, this expression would be evaluated
UPDATE:
As an FYI: The resulting test of both sides of that conditional expression above are equal, so that cryptic code is not even necessary.
You could replace that with this:
var toDraw = from tile in testArr.AsEnumerable()
where
((tile.Ending_Date >= DateTime.Now || tile.Ending_Date == DateTime.MinValue) &&
((tile.Sales_Code == null) || (tile.Sales_Code.ToString() == customerNumber) || (tile.Sales_Code.ToString() == cpg)) &&
(tile.Unit_Price != 0))
select tile;