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());
}
Related
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;
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()) || ...
I have Table HR_Travel(TravelID, TravelCode....) and HR_TravelDocuments(TravelDocID, TravelID, DocUrl)
FromDate = FromDate.AddDays(1);
ToDate = ToDate.AddDays(1);
List<dynamic> Lst = new List<dynamic>();
var queryTravelDetails = from t in db.HR_TravelDetails
where ((t.StatusDate >= FromDate && t.StatusDate <= ToDate)
&& (t.EmpID == EmpID || EmpID == 0) && (t.TravelStatus == TravelStatus || TravelStatus == "All"))
orderby t.StatusDate descending
select new
{
TravelID = t.TravelID,
TravelSubID = db.HR_TravelDetails.Where(i => i.TravelID == 0).FirstOrDefault().TravelID == null ? 0 : db.HR_TravelDetails.Where(i => i.TravelID == 0).FirstOrDefault().TravelID,
t.TravelCode,
t.EmpID,
EmpName = db.EE_Employee.Where(i => i.EmpID == t.EmpID).FirstOrDefault().EmpName,
t.CellNo,
t.BoardingForm,
t.DestinationTO,
t.JournyDate,
t.Purpose,
t.Organization,
t.TravelStatus,
DocUrl = DocUrl = string.Join(",",( db.HR_TravelDocuments.Where(i => i.TravelID == t.TravelID && i.TravelSubID == 0).Select(i => i.DocUrl).ToList()))
};
foreach (var element in queryTravelDetails)
{
Lst.Add(element);
}
Gives the following error:
LINQ to Entities does not recognize the method 'System.String Join[String](System.String, System.Collections.Generic.IEnumerable`1[System.String])' method, and this method cannot be translated into a store expression.
The Join() method can't be used in LINQ expressions, because it cannot translate from CLR to T-SQL. Another example is that you can't use:
var itemCount = db.Table.Count(p => p.Something == SomeFunction(someVariable));
You should move the method call outside the LINQ statement:
var anotherVariable = SomeFunction(someVariable);
var itemCount = db.Table.Count(p => p.Something == anotherVariable);
I hope I explained in a good way.
EDIT: As seen in the comments before, you can also use ToArray() and when the data is loaded locally you can use functions in statements freely.
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))
I'm using lambda expression in LINQ where i have to get all the result when the conditon satisfies if not it should filter.
//Code
List<Dispatch> objDispatch = (List<Dispatch>)Session["Data"];
objDispatch = objDispatch.FindAll(dispatch => dispatch.CustomerTransName == ddlTransporterName.SelectedItem.Text && dispatch.InvoiceDate.Date >= Convert.ToDateTime(FromDate).Date && dispatch.InvoiceDate.Date <= Convert.ToDateTime(ToDate).Date);
In the above code i'm filtering the result set with some conditions in that first condition i need a help.
If the transporter name is 'ALL' it should return all the result set it matches with the Date condition or else it should return according to the TransporterName.
How can i achieve this?
With pure logic.
if(ddlTransporterName.SelectedItem.Text == "ALL") {
//return all
} else {
//Do your filter logic
}
Or, with less repitive code:
objDispatch = objDispatch.FindAll(
dispatch => (ddlTransporterName.SelectedItem.Text == "ALL" || dispatch.CustomerTransName == ddlTransporterName.SelectedItem.Text)
&& dispatch.InvoiceDate.Date >= Convert.ToDateTime(FromDate).Date
&& dispatch.InvoiceDate.Date <= Convert.ToDateTime(ToDate).Date);
string name = ddlTransporterName.SelectedItem.Text;
objDispatch = objDispatch.FindAll(dispatch =>
(name == "ALL" || dispatch.CustomerTransName == name)
&& dispatch.InvoiceDate.Date >= Convert.ToDateTime(FromDate).Date
&& dispatch.InvoiceDate.Date <= Convert.ToDateTime(ToDate).Date);
If transporter name is "ALL" then name OR condition will give true and CustomerTransName will not be checked.
If you want this to be LINQ then you need to actually use a LINQ method e.g. use Where. Also you should do your date conversions once outside if they aren't specific to the row, otherwise they will be converting everytime. Not only that, it makes for more readable code...
var selectedTransporter = ddlTransporterName.SelectedItem.Text;
var fromDate = Convert.ToDateTime(FromDate).Date;
var toDate = Convert.ToDateTime(ToDate).Date;
var query = objDispatch.Where(x => (selectedTransporter == "All" || x.CustomerTransName == selectedTransporter) && x.InvoiceDate.Date >= fromDate && x.InvoiceDate.Date <= toDate);
I think this should suffice:
List<Dispatch> objDispatch = (List<Dispatch>)Session["Data"];
List<Dispatch> filteredDispatches = objDispatch.Where(dispatch => dispatch.InvoiceDate.Date >= Convert.ToDateTime(FromDate).Date && dispatch.InvoiceDate.Date <= Convert.ToDateTime(ToDate).Date).ToList();
if (ddlTransporterName.SelectedItem.Text != "ALL")
{
filteredDispatches = filteredDispatches.Where(dispatch => dispatch.CustomerTransName == ddlTransporterName.SelectedItem.Text).ToList();
}
I think something like this should work:
List<Dispatch> objDispatch = (List<Dispatch>)Session["Data"];
var _fromDate = Convert.ToDateTime(FromDate);
var _toDate = Convert.ToDateTime(ToDate);
objDispatch = objDispatch
.FindAll(dispatch => Selector(
dispatch, ddlTransporterName.SelectedItem.Text, _fromDate, _toDate));
static bool Selector(
Dispatch dispatch, string name, DateTime fromDate, DateTime toDate)
{
if (dispatch.CustomerTransName == "ALL")
{
return dispatch.InvoiceDate.Date >= fromDate.Date
&& dispatch.InvoiceDate.Date <= toDate.Date;
}
return dispatch.CustomerTransName == name;
}