Use Lambda Expressions in a Query (C#) - c#

How can I write lambda expression to get all orders who has detail row(s) with descriptions = "PickMe" or "TakeMe"

Try:
context.Orders.Where(o => o.OrderDetails.Any(d => d.Description == "PickMe" || d.Description == "TakeMe"));

Related

Two lambda expressions in a single query

I have a list of products and I have included ProductMetadatas in the query like this:
var products = _dbContext.Set<Product>()Include(x=>x.Productmetadatas).
Where(x => x.CompanyId == LoggedInUser.CompanyId && x.Active).ToList();
Now, what I want to do is I want to filter the ProductMetadats according to the CompanyId, like
var products = _dbContext.Set<Product>()Include(x=>x.Productmetadatas).
Where(x => x.CompanyId == LoggedInUser.CompanyId && x.Active &&
x.ProductMetadatas.Where(pm => pm.CompanyId == LoggedInUser.CompanyId)).ToList();
How can I do it in a single query?
If you want all products that actually do match your current users companyId you have to change it to the following:
var products = _dbContext.Set<Product>()Include(x=>x.Productmetadatas).
Where(x => x.CompanyId == LoggedInUser.CompanyId && x.Active &&
x.ProductMetadatas.Any(pm => pm.CompanyId == LoggedInUser.CompanyId)).ToList();
As you can guess .Any() checks if any element in your list matches your LINQ expression and returns a boolean. With that your expression is valid.
Previously it could not work because .Where() returns a list of elements.
EDIT:
Alright as it was noted that you want to adjust the ProductMetdatas you can do the following:
Create an extension for IEnumerable<T>:
public static void ForEach<T>(this IEnumerable<T> source, Action<T> action)
{
foreach(T item in source)
action(item);
}
And then adjust your LINQ like this:
var products = _dbContext.Set<Product>()Include(x=>x.Productmetadatas).
Where(x => x.CompanyId == LoggedInUser.CompanyId && x.Active).
ForEach(x => x.ProductMetadatas = x.ProductMetadatas.
Where(pm => pm.CompanyId == LoggedInUser.CompanyId).ToList()).ToList();
Now you invoke a function on each element which filters the ProductMetadatas and sets the property of your product to the filtered ProductMetadatas.
You can use join to filter.
var result = (from tbl in _dbContext.Set<Product>()
join lst in ProductMetadatas on lst.CompanyID eqauls LogginInUSer.CompanyID
where tbl.CompanyId == LoggedInUser.CompanyId && tbl.Active
select tbl)

C# predicate list passed to Linq Where clause

I have a long Linq Where clause that I would like to populate with a predicate list.
List<Expression<Func<Note, bool>>> filters = new List<Expression<Func<Note, bool>>>();
filters.Add(p => p.Title != null && p.Title.ToLower().Contains(searchString));
filters.Add(p => p.Notes != null && p.Notes.ToLower().Contains(searchString));
filters.Add(GlobalSearchUser((List < User > users = new List<User>() { p.user1, p.user2, p.user3, p.user4 }), searchString));
notes = dataAccess.GetList<Note>(pn => pn.ProjectVersionID == projectVersionID, filterExtensions.ToArray())
.Where(filters.ToArray()).Take(10).ToList();
However I'm getting this error:
cannot convert from 'System.Linq.Expressions.Expression<System.Func<project.Contracts.DTOs.Note,bool>>[]' to 'System.Func<project.Contracts.DTOs.Note,bool>'
Which is an error on the .where clause. Pulling out the .where compiles just fine.
I think great answer from Hogan can be simplified and shorten a bit by use of Any and All Linq methods.
To get items that fulfill all the conditions:
var resultAll = listOfItems.Where(p => filters.All(f => f(p)));
And to get the items that fulfill any condition:
var resultAny = listOfItems.Where(p => filters.Any(f => f(p)));
There are at least two errors in your code:
List<Expression<Func<Note, bool>>> filters = new List<Expression<Func<Note, bool>>>();
change it to
List<Func<Note, bool>> filters = new List<Func<Note, bool>>();
You don't need Expression trees here. You are using IEnumerable<>, not IQueryable<>
notes = dataAccess.GetList<Note>(pn => pn.ProjectVersionID == projectVersionID, filterExtensions.ToArray())
.Where(filters.ToArray()).Take(10).ToList();
There .Where() accepts a single predicate at a time. You could:
notes = dataAccess.GetList<Note>(pn => pn.ProjectVersionID == projectVersionID, filterExtensions.ToArray())
.Where(x => filters.All(x)).Take(10).ToList();
or various other solutions, like:
var notesEnu = dataAccess.GetList<Note>(pn => pn.ProjectVersionID == projectVersionID, filterExtensions.ToArray())
.AsEnumerable();
foreach (var filter in filters)
{
notesEmu = notesEmu.Where(filter);
}
notes = notesEnu.Take(10).ToList();
Because all the .Where() conditions are implicitly in &&.
You have to loop over your filters and run a test on each one.
You can do it with linq like this to return true if any of your filters are true:
.Where(p => { foreach(f in filters) if (f(p) == true) return(true); return(false)})
or like this to to return true if all of your filters are true:
.Where(p => { foreach(f in filters) if (f(p) == false) return(false); return(true)})
You can't just pass an array of predicates to the where method. You need to either iterate over the array and keep calling Where() for each expression in the array, or find a way to merge them all together into one expression and use that. You'll want to use LinqKit if you go the second route.

Linq Where/OrderBy string to int

I have seen similar questions on here but none of the answers are working for my linq query.
I am trying to convert a string to integer on the .ThenBy()
dbResults = gaResultDetails.All
.Where(c => c.ContentLink.Id == contentId && c.RequestType.Id == requestTypeId)
.OrderBy(c => c.DateFrom)
.ThenBy(c => int.Parse(c.Data_2)).Take(Take).ToList();
Please note I am using nHibernate for data access and with the above expression get the following error:
[NotSupportedException: Int32 Parse(System.String)]
Help!
Some functions are not supported by the nhibernate linq expression builder, try this:
dbResults = gaResultDetails.All
.Where(c => c.ContentLink.Id == contentId && c.RequestType.Id == requestTypeId)
.AsEnumerable()
.OrderBy(c => c.DateFrom)
.ThenBy(c => int.Parse(c.Data_2))
.Take(Take)
.ToList();
Might not be ideal performance-wise, but should accomplish what you need.
This is just a shot in the dark. If the parse doesn't work in the ThenBy, it probably won't in the let but it's worth a shot. In LINQ syntax, cuz I like it better:
dbResults = (from c in gaResultDetails.All
where c.ContentLink.Id == contentId
&& c.RequestType.Id == requestTypeId
let nData2 = int.Parse(c.Data_2)
orderby c.DateFrom, nData2)
.Take(Take)
.ToList();
It seems like your ORM tries to perform casting on the SQL server side.
Try to evaluate data before casting, e.g. :
dbResults = gaResultDetails.All
.Where(c => c.ContentLink.Id == contentId && c.RequestType.Id == requestTypeId)
.OrderBy(c => c.DateFrom).ToList()
.ThenBy(c => int.Parse(c.Data_2)).Take(Take).ToList();

How to implement "or" in request?

i have this query:
var TheQuery = db.Conventions.Where(p =>
p.Participants.Select(q => q.intituleParticipant).Contains(s));
and I need to add other conditions...
How is it possible to do it?
Put this in your query ||
or --> ||
var TheQuery = db.Conventions.Where(p => p.Participants.Select(q => q.intituleParticipant).Contains(s) || other conditions);
Pretty much the same way you'd add another condition in regular C#, by using the || (OR) operator.
var TheQuery = db.Conventions.Where(p =>
p.Participants.Select(q => q.intituleParticipant).Contains(s) ||
othercondition);
You want the || operator, same as you would use in an if statement.

Subquery in a Lambda Expression or LINQ

How can you write this query using a lambda expression or LINQ:
SELECT *
FROM vehicles
WHERE (memo1 like '%CERTIFIED%' OR memo2 = 'CERTIFIED')
AND stockno IN (SELECT stockno FROM udealer2 where ACC='UCERT')
ORDER BY model, days DESC
Not knowing much about your model, here is a blind mechanical translation of your query:
vehicles.Where( v =>
(SqlMethods.Like(v.memo1, "%CERTIFIED%") || v.memo2 == "CERTIFIED") &&
udealer2.Any(d => d.ACC == "UCERT" && d.stockno == v.stockno)
).OrderBy(v => v.model)
.ThenByDescending(v => v.days)
where Dealers.Any(d => d.Account == "UCERT" && something.StockNo == d.StockNo)

Categories

Resources