This question already has answers here:
Only do Where condition if a value is passed in
(4 answers)
Closed 9 years ago.
public List<..> GetSomething(int column1Value, int column2Value, string column3Value)
{
from t1 in this.DataContext.Table1
where t1.column1 == column1Value &&
t1.column2 == column2Value &&
t1.column3 == column3Value
}
Now I want to re-use the above query i.e. don't want to duplicate it, but the ONLY difference is I want the t1.column3 == column3Value to be option so I call this like:
GetSomething(1,2,"HELLO");
and
GetSomething(1,2);
Is it possible to make this part of the where clause conditional? Meaning if you pass in "", then it ignores that clause?
Yes, just break your statement into two parts like this:
var query = this.DataContext.Table1
.Where( x => column1 == column1Value && x.column2 == column2Value);
if ( column3Value != "" )
query = query.Where( x => x.column3 == column3Value);
// Your existing processing of query
Try this:
public List<..> GetSomething(int column1Value, int column2Value, string column3Value = null) {
from t1 in this.DataContext.Table1
where t1.column1 == column1Value &&
t1.column2 == column2Value &&
(column3Value == null ? true : t1.column3 == column3Value)
}
I suggest ou to define OR operator in order to define such as optional
Make the parameter optional, and test for the lack of it:
public List<..> GetSomething(int column1Value, int column2Value,
string column3Value = null)
{
from t1 in this.DataContext.Table1
where t1.column1 == column1Value &&
t1.column2 == column2Value &&
(column3Value == null || t1.column3 == column3Value)
}
Related
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());
}
This question already has answers here:
Dynamic where clause (OR) in Linq to Entities
(2 answers)
Closed 5 years ago.
I am working in ASP.NET MVC, I have a scenario where user can select multiple options to get list of doctors, this is how my action looks like.
public JsonResult DoctorsList(int? specialization , int? city, int? area, int? insurance_company, string doctor_name )
Any of these arguments can have some value and any number of them can be null also all of can be null in that I will return all the records.
Now I know a long and complicated way where I can make different combinations of these arguments and check which one is null and which one is not and then write my query based on that.
But is there any other shorter more efficient way?
Right now I am using OR conditions to get records like this
var doctors = db.Doctors.Where(e =>
e.specialization == specialization ||
e.Clinics.FirstOrDefault(cs => cs.doctor_id == e.doctor_id).Area.city_id == city ||
e.Clinics.FirstOrDefault(cs => cs.doctor_id == e.doctor_id).area_id == area ||
e.Clinics.FirstOrDefault(cs => cs.doctor_id == e.doctor_id).ClinicInsuranceCompanies
.Select(sin=>sin.company_id).ToList().Contains(insurance_company) ||
e.first_name == doctor_name ||
e.last_name == doctor_name
)
.Select(s => new
{
doctor_name = s.first_name + " " + s.last_name
}).ToList();
But I want it to work in combinations, For Example Selecting Doctors with specialization_id = 1 and city_id=2 , of other combinations like this. But OR condition will be true if only one condition matches
For your scenario i think this approach might work rather than going around if else conditions. And i think && should be used to filter out exactly but you could use || operator if thats what you want,
var doctors = db.Doctors.Where(e =>
(specialization != null && e.specialization == specialization) &&
(city != null && e.Clinics.FirstOrDefault(cs => cs.doctor_id == e.doctor_id).Area.city_id == city) &&
(area != null && e.Clinics.FirstOrDefault(cs => cs.doctor_id == e.doctor_id).area_id == area) &&
(insurance_company != null && e.Clinics.FirstOrDefault(cs => cs.doctor_id == e.doctor_id).ClinicInsuranceCompanies
.Select(sin => sin.company_id).ToList().Contains(insurance_company)) &&
(doctor_name != "" && e.first_name == doctor_name || e.last_name == doctor_name)
)
.Select(s => new
{
doctor_name = s.first_name + " " + s.last_name
}).ToList();
This is what I was looking for #imanshu15 answer gave me a hint.
var doctors = db.Doctors.Where(e =>
(specialization != null && e.specialization == specialization) || (specialization == null)
).Where(e =>
(city != null && e.Clinics.FirstOrDefault(cs => cs.doctor_id == e.doctor_id).Area.city_id == city) || (city == null)
).Where(e =>
(area != null && e.Clinics.FirstOrDefault(cs => cs.doctor_id == e.doctor_id).area_id == area) || (area == null)
).Where(e =>
(insurance_company != null && e.Clinics.FirstOrDefault(cs => cs.doctor_id == e.doctor_id).ClinicInsuranceCompanies
.Select(sin => sin.company_id).ToList().Contains(insurance_company)) || (insurance_company == null)
).Where(e =>
(doctor_name != null && e.first_name == doctor_name) || (doctor_name == null)
)
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");
}
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))
This question already has answers here:
How to get the index of an element in an IEnumerable?
(12 answers)
Closed 8 years ago.
kriteriji is type of List<Kriteriji>
var doc = kriteriji.Where(k => k.Ean == txtEan.Text
&& k.PredmetObravnave == acPredmetObravnave.Text
&& k.Tse == txtTse.Text
&& k.DejanskaKolicina == Convert.ToInt32(txtKolicina.Text)
&& k.KratekNazEnoteMere == acKNEnotaMere.Text
&& k.OznakaLokacije == acOznakaLokacije.Text
&& k.OznakaZapore == txtZapora.Text
&& k.SarzaDob == txtSarzaDobavitelja.Text
&& k.Sarza == txtSarza.Text
&& k.DatumVelOd == datumOd
&& k.DatumVelDo == datumDo).FirstOrDefault();
Now when I get doc how can I know in which position in List<kriteriji> is? I need to now if is in first, second,...
I think you could create a (index , value) keyvaluepaire object at first and then retrive it like
var doc = kriteriji.Select((value, index) => new { index, value })
.Where(k => k.value.Ean == txtEan.Text
&& k.value.PredmetObravnave == acPredmetObravnave.Text
&& k.value.Tse == txtTse.Text
&& k.value.DejanskaKolicina == Convert.ToInt32(txtKolicina.Text)
&& k.value.KratekNazEnoteMere == acKNEnotaMere.Text
&& k.value.OznakaLokacije == acOznakaLokacije.Text
&& k.value.OznakaZapore == txtZapora.Text
&& k.value.SarzaDob == txtSarzaDobavitelja.Text
&& k.value.Sarza == txtSarza.Text
&& k.value.DatumVelOd == datumOd
&& k.value.DatumVelDo == datumDo).FirstOrDefault();
then you could get the index like
Console.WriteLine(doc.index);
You can use an overload for select that will take an index and a Kriteriji.
Here is the documentation.
Then you could select an anonymous object with an Index property and a Doc property. If you would use IndexOf this will cause another search throughout the list while you already have that data.
Use the IndexOf method:
kriteriji.IndexOf(doc);
Try this:
var position = kriteriji.IndexOf(doc);
You can find out the index with:
kriteriji.IndexOf(doc.First());