I have 3 search textbox values. i need to check string.isnullorEmpty for each variable and have to compare with the linq query.
My Text Values:
Manufacturer
Project Code
PartNo
Conditions:
if i search any one of the above i should get the result
If i enter 3 box values i should get the result
If i enter any 2 then i should get result.
My code as follows
if (!string.IsNullOrEmpty(manufacturer))
{
var filteredResult = _entity.MaterialMasters.Where(x => x.Manufacturer == manufacturer);
}
if (!string.IsNullOrEmpty(projectcode))
{
var filteredResult = _entity.MaterialMasters.Where(x => x.ProjectCode== projectcode);
}
if (!string.IsNullOrEmpty(part))
{
var filteredResult = _entity.MaterialMasters.Where(x => x.Part== part);
}
To avoid multiple conditions how to make dynamic where clause for this? Please find out the solution for this..
He wants to get rid of the if statements and write this all as a linq query. I think you want something like this
.Where(
s =>
(string.IsNullOrEmpty(manufacturer) | (s.Manufacturer == manufacturer)) &&
(string.IsNullOrEmpty(projectcode) | (s.ProjectCode == projectcode)) &&
(string.IsNullOrEmpty(part) | (s.Part== part))
).ToList();
You can just tag on multiple Where clauses
var filteredResult = _entity.MaterialMasters;
if (!string.IsNullOrEmpty(manufacturer))
filteredResult = filteredResult.Where(x => x.Manufacturer == manufacturer);
}
if (!string.IsNullOrEmpty(projectcode))
filteredResult = filteredResult.Where(x => x.ProjectCode == projectcode);
}
if (!string.IsNullOrEmpty(part))
filteredResult = filteredResult.Where(x => x.Part == part);
}
They will work cumulatively, meaning that you can supply 1, 2 or 3 of the parameters and you'll get the appropriate results.
var filteredResult =
_entity.Where(
ent =>
(!string.IsNullOrEmpty(manufacturer) && ent.Manufacturer == manufacturer)
|| (!string.IsNullOrEmpty(projectcode) && ent.ProjectCode == projectcode)
|| (!string.IsNullOrEmpty(part) && ent.Part == part));
This will get you any result for manufacturer, projectCode and part in one place.
Related
Previously, I had great help on my previous question, thank you vyrp
,
How do I create and populate a dynamic object using a dynamically built lambda expression
I'm now looking to search the dynamic object, and as before, I don't know the objects properties, and therefore what I'm searching until runtime.
Here's the code that builds the dynamic object:
// Get list of optional fields
var optFieldList = await _tbList_FieldRepository.GetAsync(lf => lf.ListID == listId && lf.DisplayInList == true);
// order list of optional fields
optFieldList.OrderBy(lf => lf.DisplayOrder);
// Get base Data excluding Inactive if applicable
IEnumerable<tbList_Data> primaryData = await _tbList_DataRepository.GetAsync(ld => ld.ListID == listId && (ld.IsActive == includeInactive ? ld.IsActive : true));
// Build IEnumerable<dynamic> from base results plus any optional fields to be displayed in table
var results = primaryData.Select(pd => {
dynamic result = new System.Dynamic.ExpandoObject();
result.Id = pd.ID;
result.PrimaryData = pd.PrimaryData;
result.DisplayOrder = pd.DisplayOrder;
result.IsActive = pd.IsActive;
foreach (var optField in optFieldList)
{
switch (optField.FieldType.ToLower()) {
case "text":
((IDictionary<string, object>)result).Add(optField.FieldName, pd.tbList_DataText.Where(ld => ld.DataRowID == pd.ID && ld.ListColumnID == optField.ID).Select(ld => ld.DataField).DefaultIfEmpty("").First());
break;
}
}
return result;
});
For the purpose of testing, I have 2 dynamic fields, "PhoneNumber" and "FuelType"
I can search the known field(s) i.e. PrimaryData, no problem, as below.
results = results.Where(r => r.PrimaryData.Contains(searchString));
And the following will work if I know the field PhoneNumber at design time
results = results.Where(r => r.PhoneNumber.Contains(searchString));
but what I want to do, is something like:
results = results.Where(r => r.PrimaryData.Contains(searchString)
|| foreach(var optField in optFieldList)
{
r.optField.FieldName.Contains(searchString)
})
ending up with
results = results.Where(r =>
r.PrimaryData.Contains(searchString)
|| r.PhoneNumber.Contains(searchString) ||
r.FuelType.Contains(searchString));
but obviously that code doesn't work. I've tried a bunch of different attempts, none successful, so I'm looking for suggestions. Thanks
Since you know that the dynamic element of your query is actually ExpandoObject, hence IDictionary<string, object>>, you can safely cast it to dictionary interface and use it to access the property values by name, while Enumerable.Any method can be used to simulate dynamic || condition:
results = results.Where(r => r.PrimaryData.Contains(searchString)
|| optFieldList.Any(f =>
{
object value;
return ((IDictionary<string, object>)r).TryGetValue(f.FieldName, out value)
&& value is string && ((string)value).Contains(searchString);
}));
I have some table and the following condition of query: if parameter A is null take all, if not, use it in the query. I know how to do that in 2 steps:
List<O> list = null;
if (A = null)
{
list = context.Obj.Select(o => o).ToList();
}
else
{
list = context.Obj.Where(o.A == A).ToList();
}
Is it possible to have the same as one query?
Thanks
How about:
list = context.Obj.Where(o => A == null || o.A == A)
.ToList();
You can do it in one query but still using a condition:
IEnumerable<O> query = context.Obj;
if (A != null)
{
query = query.Where(o => o.A == A);
}
var list = query.ToList();
Or you could use a conditional operator to put the query in a single statement:
var query = A is null ? context.Obj : context.Obj.Where(o => o.A == A);
var list = query.ToList();
I would personally suggest either of the latter options, as they don't require that the LINQ provider is able to optimise away the filter in the case where A is null. (I'd expect most good LINQ providers / databases to be able to do that, but I'd generally avoid specifying a filter when it's not needed.)
I opted for
var list = context.Obj.Where(o => A.HasValue ? o.a == A : true);
I would probably write the query like this:
IQueryable<O> query = context.Obj;
if (A != null)
query = query.Where(o => o.A == A);
var list = query.ToList()
It's not one expression, but I think it's quite readable.
Also, this code assumes that context.Obj is IQueryable<O> (e.g. you are using LINQ to SQL). If that's not the case, just use IEnumerable<O>.
I am writing a Linq Query. Is there a way that I can concatenate to query based on some if conditions?
Like on query is
from res in _db.Person
where res.Departments.ID == deptId
select res;
And if I have a condition true, I would like it to be something like
from res in _db.Person
where res.Departments.ID == deptId && res.Departments.Type == deptType
select res;
Implementing an "AND" type condition is easy - and easier using extension method syntax to call Where multiple times:
IQueryable<Person> people = _db.Person
.Where(res => res.Departments.ID == deptId);
if (deptType != null)
{
people = people.Where(res => res.Departments.Type == deptType);
}
// Potentially add projections etc.
EDIT: If you want "OR" functionality, it's slightly tricky from scratch, as you need to mess around with expression trees. I suggest you use the PredicateBuilder library:
Expression<Func<Person, bool> predicate = res => res.Departments.ID == deptId;
if (deptType != null)
{
predicate = predicate.Or(res => res.Departments.Type == deptType);
}
IQueryable<Person> people = _db.Person.Where(predicate);
Assuming your condition is in the variable condition
from res in _db.Person
where res.Departments.ID == deptId && (!condition || res.Departments.Type == deptType)
select res;
Version that does or as requested
from res in _db.Person
where res.Departments.ID == deptId || (condition && res.Departments.Type == deptType))
select res;
Alternatively you may wish to use predicate builder
I would do something like this:
var result = _db.Person.Where(x=>x.Departments.ID == deptId);
if(myCondition)
result = result.Where(x=>x.Departments.Type == deptType);
The query is not actually executed until you attempt to enumerate result, so you can keep adding conditions as long as you like.
I have a scenario where I have to use a dynamic where condition in LINQ.
I want something like this:
public void test(bool flag)
{
from e in employee
where e.Field<string>("EmployeeName") == "Jhom"
If (flag == true)
{
e.Field<string>("EmployeeDepartment") == "IT"
}
select e.Field<string>("EmployeeID")
}
I know we can't use the 'If' in the middle of the Linq query but what is the solution for this?
Please help...
Please check out the full blog post: Dynamic query with Linq
There are two options you can use:
Dynamic LINQ library
string condition = string.Empty;
if (!string.IsNullOrEmpty(txtName.Text))
condition = string.Format("Name.StartsWith(\"{0}\")", txtName.Text);
EmployeeDataContext edb = new EmployeeDataContext();
if(condition != string.empty)
{
var emp = edb.Employees.Where(condition);
///do the task you wnat
}
else
{
//do the task you want
}
Predicate Builder
Predicate builder works similar to Dynamic LINQ library but it is type safe:
var predicate = PredicateBuilder.True<Employee>();
if(!string.IsNullOrEmpty(txtAddress.Text))
predicate = predicate.And(e1 => e1.Address.Contains(txtAddress.Text));
EmployeeDataContext edb= new EmployeeDataContext();
var emp = edb.Employees.Where(predicate);
difference between above library:
PredicateBuilder allows to build typesafe dynamic queries.
Dynamic LINQ library allows to build queries with dynamic Where and OrderBy clauses specified using strings.
So, if flag is false you need all Jhoms, and if flag is true you need only the Jhoms in the IT department
This condition
!flag || (e.Field<string>("EmployeeDepartment") == "IT"
satisfies that criterion (it's always true if flag is false, etc..), so the query will become:
from e in employee
where e.Field<string>("EmployeeName") == "Jhom"
&& (!flag || (e.Field<string>("EmployeeDepartment") == "IT")
select e.Field<string>("EmployeeID")
also, this e.Field<string>("EmployeeID") business, smells like softcoding, might take a look into that. I guess
from e in employee
where e.EmployeeName == "Jhom"
&& (!flag || (e.EmployeeDepartment == "IT")
select e.EmployeeID
would be more compact and less prone to typing errors.
EDIT: This answer works for this particular scenario. If you have lots of this kinds of queries, by all means investingate the patterns proposed in the other answers.
You can chain methods :
public void test(bool flag)
{
var res = employee.Where( x => x.EmployeeName = "Jhom" );
if (flag)
{
res = res.Where( x => x.EmployeeDepartment == "IT")
}
var id = res.Select(x => x.EmployeeID );
}
from e in employee
where e.Field<string>("EmployeeName") == "Jhom" &&
(!flag || e.Field<string>("EmployeeDepartment") == "IT")
select e.Field<string>("EmployeeID")
You can call LINQ methods explicitly and chain them conditionally.
public IEnumerable<string> FilterEmployees (IEnumerable<Employee> source, bool restrictDepartment)
{
var query = source.Where (e => e.Field<string>("EmployeeName") == "Jhom");
if (restrictDepartment) // btw, there's no need for "== true"
query = query.Where (e => e.Field<string>("EmployeeDepartment") == "IT");
return query.Select (e => e.Field<string>("EmployeeID"));
}
I have a database table that contains "commands" and "states". Each command can have several states, and the user is able to configure this when search. For example, the command could be "Run" and it could have two states: "Fast" and "Slow".
I want to search my table for all commands called "Run" with "Fast" or "Slow". This is pretty simple to do:
var results = from t in table
where t.Command == "Run" &&
(t.State == "Fast" || t.State == "Slow")
return t;
However the user could also search command "Walk" with state "Fast", and so the query would look like:
var results = from t in table
where (t.Command == "Run" &&
(t.State == "Fast" || t.State == "Slow")) ||
(t.Command == "Walk" &&
t.State == "Fast")
return t;
There is a potential for as many searches like this, and I'm wondering how to combine them in a loop of sorts.
I can't do this:
foreach(var command in commands)
{
foreach(var state in command.states)
{
results = from t in table
where t.Command == command.Command &&
t.State == state;
}
}
because once it searches for "Run", "Walk" would be left out of results so asking for "Walk" would result in NO results at all.
Does anyone know of a good way to do this?
Use Joe Albahari's PredicateBuilder to build a predicate:
var predicate = PredicateBuilder.False<Entry>();
foreach(var command in commands)
{
foreach(var state in command.states)
{
predicate = predicate.Or(p => p.Command == command.Command && p.State == state);
}
}
var query = table.Where(predicate);
Or a more LINQ-heavy version:
var commandStates = from c in commands
from s in c.states
select new {c.Command, State = s};
var predicate = commandStates.Aggregate(
PredicateBuilder.False<Entry>(),
(pred, e) => pred.Or(p => p.Command == e.Command && p.State == e.state));
var query = table.Where(predicate);