Can we delete clauses from linq expression? - c#

I was wondering whether it's possible to add/remove a where clause from a linq expression/ query operators.
Eg :-
var qry = from e in emp where(e => e.salary > 5000) select e;
Is it possible to remove where expression at a later stage?
Thanks in advance :)

Yes, it is possible, but you need to implement an ExpressionVisitor class to evaluate the composite expression and change it according to your needs. Unless you are doing something relatively complex there is probably a better way to accomplish what you want.

you can only adjust your filtering as far as i know
for example if are trying to delete based on condition e.salary > 5000 , they you should try something like
var diffQry = from e in emp where(e => e.salary <= 5000) select e;

If you want to programmatically add and remove where clauses you can use query operators.
var query = emp.Select(x => x);
if (someCondition)
query = query.Where(x => x.Price > 50);
You need to expand on your question a little more.

If qry is an IQueryable<T> -- for example, a LINQ-to-SQL or LINQ-to-Entities query -- then it should be possible to analyse the underlying expression tree and build a new one excluding the Where clause.
If qry is a plain IEnumerable<T> -- for example, a LINQ-to-Objects query -- then this can't be done since there will be no expression tree to analyse.

I think WHERE clause is required if there is a conditional query. Otherwise (if no condition) you can use:
var qry = from e in emp select e;

Related

Convert LINQ method syntax with method withing .Select() to LINQ query syntax

I currently have the following code:
dataSource.Where(row => row.Value == 1)
.Select(row => {row["Text"] = translatedText; return row;})
.Single();
So my goal is to select the DataRow with "Value=1" and at the same time set the value in the "Text"-column to some other value (in my case a string-variable transalatedText).
This already works fine with the method chain mentioned above but I generally prefer the LINQ syntax. Is there a possibility to translate this method chain to LINQ?
My problem is that I do not know how to translate the function in the Select-method to LINQ-format. I dont want to create a new DataRow but want to really edit the selected one. (So I don't want to use from x in y where z select new DataRow(...) but to really edit my x if possible)
Thanks!
Is there a possibility to translate this method chain to LINQ?
(By "to LINQ" I believe you mean "to query expression syntax".)
Not directly, no. Effectively, you can only convert expression-bodied lambda expressions into query syntax. There's a good reason for that: LINQ is designed not to have side effects, whereas your "query" does have side-effects.
I would personally write your code like this instead:
var row = DataSource.Single(row => row.Value == 1);
row["Text"] = translatedText;
That neatly separates the querying from the side-effect. If you really, really want to use query expression syntax, you could write:
var query = (from row in DataSource
where row.Value == 1)
select HorribleMutatingMethod(row)).Single();
...
private DataRow HorribleMutatingMethod(DataRow row)
{
row["Text"] = translatedText;
return row;
}
... but please don't.

lambda equivalent to sql update with joins

I have 2 sets of data.
What would be the lambda syntax equivalent to this sql update statement ?
UPDATE Customers1
SET Customers1.Email = Customers2.Email
JOIN Customers2 ON Customers1.ID = Customers2.ID
Lambdas are just a way of writing anonymous methods: x => { body }. I assume you actually mean LINQ.
There is no equivalent, because the Q in LINQ stands for query. LINQ queries data, it doesn't change it.
As DanielHilgarth said just to use lambda or even LINQ is not enough here.
I assume you'd need something like:
foreach(var customer1 in customers1) {
var customer2 = customers2.FirstOrDefault(c2 => customer1.ID.Equals(c2.ID));
if (customer2 != null) customer1.Email = customers2.Email;
}
So, lambda is a chunk of the whole implementation.

Where with IN operator using Linq on NHibernate

I have a linq query with NHibernate using Session.Query<T> method and I in this query I Fetch some complex properties and collection properties. I would like to know, how can I add an condition with IN operator from an int[]? Look my code:
public IEnumerable<Product> GetProducts(int[] idCategories)
{
// how to add IN condition here or a subquery
var query = Session.Query<Product>()
.Where(?????)
.Fetch(x=>x.Category)
.FetchMany(x=>x.Status).ThenFetch(x=>x.Item);
return query.ToList();
}
I have another method doing a query to get this int[] and I would like to apply it here, or if is there any way to add this subquery on the IN operator, I really appreciate!
OBS: I could convert int[] to List<int> if its necessary.
Edits
I got this int[] by a query like:
return session.Query<Category>.Where(...).Select(x => x.Id).ToArray();
My second question is, how could I add this query as a subquery to filter by category?
Thank you!
You don't really need the IN operator. You can just do it like this:
.Where(x => idCategories.Contains(x.Category))
Note: Contains is an extension method. You need to ensure that you have a using statement for System.Linq, but you probably already have it.
Take a look on Restrictions, for example
var query = Session.Query<Product>()
.Where(Restrictions.In(Projections.Property<Product>x=>x.Id),idCategories))
.Fetch(x=>x.Category)
.FetchMany(x=>x.Status).ThenFetch(x=>x.Item);
About sub query, you need Subqueries class
var query = Session.Query<Product>()
.Where(Subqueries.WhereProperty<Product>(x=>x.Id)...)
.Fetch(x=>x.Category)
.FetchMany(x=>x.Status).ThenFetch(x=>x.Item);
for more details please look here How to do subqueries in nhibernate?

Linq - SQL passing parameters into GroupBy()

Using a linq query, how can i pass parameters into the groupby function? Depend on user selection, it will be grouped differently
var query = (from to in OrderQuery
group to by to.FromDateUtc into groupedDate
let grouped = groupedDate.GroupBy(o => o.Name)
I would like to pass different groupby values. Any idea?
Cheers
Generally speaking, you need different queries for this. The same goes for building up different WHERE or Where(...) clauses based on user selection:
var query = OrderQuery;
if (userSelection == "GroupByName") {
query = from to in query
group to by to.FromDateUtc into groupedDate
let grouped = groupedDate.GroupBy(o => o.Name);
}
else if (userSelection == "GroupBySomethingElse") {
query = from to in query
group to by to.FromDateUtc into groupedDate
let grouped = groupedDate.GroupBy(o => o.SomethingElse);
}
You'll want to prepare as much common logic as possible before you apply the grouping to query. Because LINQ uses deferred execution you can modify query as much as you need before enumerating the result and you will not incur a performance hit.
If you are trying to do something like this
SELECT * FROM <TableName> GROUP BY <Column1>,<Column2>
Then, take a look at this post
Group By Multiple Columns

Linq to SQL - Query

I am trying to mimic below statement in Linq to SQL.
WHERE (rtrim(posid) like '%101' or rtrim(posid) like '%532')
I statement basically determine if posid ends with 101 or 532. In the above example I am only making 2 comparisons but their could be 1 to N comparisons all joined with OR. I store the comparison values (101,532,...) in a generic list that I send to my Linq to SQL method.
I have tried to mimic above SQL using a where clause unsuccessfully (example below):
var PosNum = new List<string>();
PosNum.Add("101");
PosNum.Add("532");
var q = (from a in context.tbl_sspos select a);
q = q.Where(p => PosNum.Contains(p.posid.Trim()));
The issue with the above where clause is that it tries to do an exact match rather I want an ends with comparison.
How would I mimic the SQL statement in Linq to SQL.
Thank You in advance for any help / advice you can provide.
I would use String.EndsWith();
This will check the end of the string rather than entire contents of it.
var q = (from a in context.tbl_sspos select a);
q = q.Where(p => p.posid.EndsWith("102") || p.posid.EndsWith("532"));
In EF 4 you can use the StartsWith / EndsWith methods by now. Might also work in LINQ to SQL.
UPDATE
Just realized that you are trying todo this against multiple values (PosNum), I don't think that this is directly supported currently. You can however concatenate multiple Where()clauses to get the result.
UPDATE 2
As AdamKing pointed out concatenating the where clauses was filtering against all PosNum values, here is the corrected version:
var baseQuery = (from a in context.tbl_sspos select a);
IEnumerable<YourType> q = null;
foreach(var pos in PosNum)
{
if(q == null)
q = baseQuery.Where(a => a.posid.EndsWith(pos));
else
q = q.Union(baseQuery.Where(a => a.posid.EndsWith(pos)));
}
This is not as pretty anymore, but works nonetheless.

Categories