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);
Related
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.
I have the following query:
db.Context.SomeTable
.Where(x => x.abc == someAbc && x.zyx == someZyx)
.ForEach(y =>
{
y.AuditId = newAuditId;
y.TimeStamp = newTimestamp;
});
I would like to get the actual SQL query out of the ForEach statement.
If I do just the following:
var selectQuery = db.Context.SomeTable
.Where(x => x.abc == someAbc && x.zyx == someZyx);
I can get the following query from selectQuery variable:
SELECT
[Extent1].[abc] AS [abc],
[Extent1].[zyx] AS [zyx]
--skipping some [Extent1]. statements for simplicity here
FROM
[dbo].[SomeTable] AS [Extent1]
WHERE
([Extent1].[abc] = #p__linq__0) AND ([Extent1].[zyx] = #p__linq__1)
Which I can then run outside of Visual Studio, analyze the performance of it, etc.
How would I do this for the ForEach statement?
ForEach execute and fetch the data from your server. ForEach is not translated into SQL. It just execute the Linq To Entities you just wrote :
var selectQuery = db.Context.SomeTable
.Where(x => x.abc == someAbc && x.zyx == someZyx);
Which generate the SQL you worte in your question.
As mentioned, ForEach does not get translated into a SQL statement. If you want to make those changes in .NET and save them back to the database, then you'll need to call SaveChanges to update the data source:
var items = db.Context.SomeTable
.Where(x => x.abc == someAbc && x.zyx == someZyx);
foreach(var item in items)
{
item.AuditId = newAuditId;
item.TimeStamp = newTimestamp;
}
db.Context.SaveChanges();
Take a look at setting this.
https://msdn.microsoft.com/en-us/library/system.data.entity.database.log(v=vs.113).aspx
I've used this in the past, but by the time you get the query it has already been executed. This may or may not help you.
I think you forgot to mention 'ToList()' before 'foreach'. you need an array or list to do the loop.
Here is my example,
public HomePageBannerModel GetBannerImage()
{
var banner = new HomePageBannerModel();
_jBannerRepository.Table.Where(x => x.BannerType == BannerTypes.Home).ToList()
.ForEach(y =>
{
switch (y.Size)
{
case "M":
banner.Md = _pictureService.GetPictureUrl(y.PictureId);
break;
case "S":
banner.Sm = _pictureService.GetPictureUrl(y.PictureId);
break;
default:
banner.Lg = _pictureService.GetPictureUrl(y.PictureId);
break;
}
});
return banner;
}
i'm trying to select values from my database, but currently i'm unable to to it and although i know its the fact that the method doesnt except the QueryBuilder class as a parameter, i dont know what to do about it. I only found solutions for querys with one parameter or all parameters are not null. In my case i've a List with ID, and 4 parameters which dont have to be passed to the function so they could be null.
My current code looks like this.
collection = db.GetCollection<Datapoint>("test");
var query = new QueryBuilder<Datapoint>();
var queryattributes = new List<IMongoQuery>();
var ids = new List<IMongoQuery>();
// Add all Attributes if there
if (fromdate != null)
{
BsonDateTime from = BsonDateTime.Create(fromdate);
queryattributes.Add(Query.GTE("UTCTimestamp", from));
}
if (to != null)
{
BsonDateTime bto = BsonDateTime.Create(to);
queryattributes.Add(Query.LTE("UTCTimestamp", bto));
}
if (evId != null)
{
queryattributes.Add(Query.EQ("EvId", evId));
}
if (evType != null)
{
queryattributes.Add(Query.EQ("EvType", evType));
}
// Add all ID's
Parallel.ForEach(idList, data =>
{
lock (query)
{
ids.Add(Query.EQ("CId", data));
}
});
// But everything in the Query
query.Or(ids);
// Add Queryattributes if there
if (queryattributes.Count > 0)
{
query.And(queryattributes);
}
var result = collection.FindAs<Datapoint>(query);
I'm trying to do it without Linq, since i found countless of test, which say that linq is much much slower, and since i want to run it as an Databasetest, i kinda need the performace to execute alot of querys.
The Linq query looks like this
var query2 =
from e in collection.AsQueryable<Datapoint>()
where idList.Contains(e.CId)
&& (evtId == null || e.EvId == evId)
&& (evType == null || e.EvType == evType.Value)
&& (fromdate == null || Query.GTE("UtcTimestamp", BsonDateTime.Create(fromdate)).Inject())
&& (to == null || Query.LT("UtcTimestamp", BsonDateTime.Create(to)).Inject())
select e;
The QueryBuilder doesn't save a query inside it. You use it to generate a IMongoQuery and then use that query to actually query the database.
It seems the end of your code should look like this;
// But everything in the Query
IMongoQuery mongoQuery = query.Or(ids);
// Add Queryattributes if there
if (queryattributes.Count > 0)
{
mongoQuery = query.And(queryattributes);
}
var result = collection.FindAs<Datapoint>(mongoQuery);
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"));
}