How to write this WHERE condition in Linq? [duplicate] - c#

This question already has an answer here:
How to express IN (list of argument) in a query LINQ?
(1 answer)
Closed 8 years ago.
How can I write this where condition in Linq?
var result = from i in context.ItemsFullDetails where i.iditem in (1,2,3,4)
where condition includes a list of id's where which be compared with the iditem column.
I am getting an error if I write in the above way.

Try this:
/*Hold here the items you want to filter by*/
var filterCriteria = new List(){1,2,3,4};
/*Get results as Ienumerable<int>*/
var result = context.ItemsFullDetails.Where(i => filterCriteria.Contains(i.iditem));
If you want to get results as list / array, you can use result.ToList() / result.ToArray()

Try this approach:
//create filter list
int[] productList = new int[] { 1, 2, 3, 4 };
// check your search item exists in the filter list
var myProducts = from p in db.Products
where productList.Contains(p.ProductID)
select p;
Reference:
What is LINQ equivalent of SQL’s "IN" keyword

You have a couple options. The first, as I see many people have suggested on this and similar posts, is to create a collection external from the LINQ query and use Contains against that:
int[] items = new[] { 1, 2, 3, 4 };
var result = from i in context.ItemsFullDetails where items.Contains(i.iditem)
But that said, if your example here is more or less what you're actually looking to do and you do have a constant set of possibilities, I'd be more tempted to write out the logic:
var result = from i in context.ItemsFullDetails where i.iditem == 1
|| i.iditem == 2
|| i.iditem == 3
|| i.iditem == 4
Now, this is nearly as pretty. I agree. But this will be the most efficient way to do what you're after, and I don't think it's unreadable enough--particularly to experienced developers who are inherently used to logic like this--to warrant a lack of efficiency. Now, obviously, this approach only works if you have a compile-time collection set. But since you did in your example, I'm assuming you will in real life. So that's what I'd do. Then you don't have to risk looping through the entire collection for every element.
Or if you need a dynamic set of conditions:
List<int> items = new List<int>() { 1, 2, 3, 4 };
items.Add(...);;
var result = from i in context.ItemsFullDetails where items.Contains(i.iditem)

Related

Using linq to check property against one of multiple possible values

Using linq to check property against one of multiple possible values. In this case when the status is 2 or 3? Can this be done without an or operator?
var x = (from b in books
where b.statusCode.Contains(2, 3))
select new ...
You could set up the list of values as a List<int>, call it something like ValueList, and then on your where line:
where ValueList.Contains(b.statusCode)
This should compare the statusCode against all list values and return the records that match, and you get the benefit of a dynamic list that can be reset with different values to return collections of other status codes.
It can be done like this (assuming that statusCode is int)
var values = new int[] { 2, 3 };
var x = (from b in books
where values.Contains(b.statusCode))
select new ...
or You can try to inline it like that:
var x = (from b in books
where (new int[] { 2, 3 }.Contains(b.statusCode)))
select new ...

How to check if a list of ids exists in db without fetching the count and compare it to the list count

I know this sounds like a duplicate question, but what I want is slightly different from other answers.
Technically I want to get this query sent to the database using Linq:
Select Count(*) = 3 From Products Where Id in (1,2,3)
Notice this query returns True if all ids exist, and False if any of them doesn't.
It is kind of Products.Exists(p => ids.Contain(p.Id)) but all the ids should exists.
Try this:
int[] ids = new int[] { 1, 3, 9, 11, 125 };
bool res = ids.All(id => Products.Select(p => p.Id).Contains(id));
This is not really a great answer because it will result in separate queries for every id in the array.
A better solution would be something like this:
var ids = new int[] { 1, 3, 9, 11, 125 };
var res = Products.Count(s => ids.Contains(s.Id)) == ids.Length;
This will result in just one query using the IN clause.

SQL IN Operator to LINQ

I need this query to be translated to Linq query
SELECT DISTINCT (pf.Id)
FROM
PF pf
LEFT JOIN FA fa on pf.id = fa.PFId
LEFT JOIN Fan f ON pf.FId = f.Id
WHERE
pf.PId=2 AND fa.AId IN (1,26) AND fa.AId NOT IN(27)
This is the LINQ query I have so far as requested
var allFansSavedAsLeads = _dbContext.PF
.Where(e => e.F.S != null &&
e.A.Any(x => x.AId==27 &&
x.AId.Equals(1) /*&&
x.AId != 27*/) &&
e.PId == pId);
I get zero results with this.
I suggest you Create two lists of Ids representing the Activities that can be included and activities which needs to be excluded. use them like the following:
List<int> IncludedIds = new List<int>(){1,26};
List<int> ExcludedIds = new List<int>(){27};
_dbContext.ProfileFans.Where(e => e.Fan.SNUrl != null &&
e.Activities.Any(x => IncludedIds.Any(x.ActivityId) &&
!ExcludedIds.Any(x.ActivityId) &&
e.ProfileId == profileId);
Please note: I used List<int> because of the example that you are given, you have to create the lists based on the data type of ActivityId
You can create a temporary ActivityList AS
var List<int> ActivityList = new List<int>() {1, 26}
and use something like
ActivityList.Contains(x => x.ActivityId)
But see sujith's answer for a more complete solution.
You don't need a whitelist and a blacklist. It's either one or the other. So I'm making a whitelist. If the allowed ActivityId is 1 or 26, then by definition it is definitely not 27, so there is no need to try and exclude it. I'm using int[] instead of List<int> given that the whitelist is likely to be static, but feel free to change this to a List<int> if you want to dynamically modify it.
int[] whiteList = { 1, 26 };
var allFansSavedAsLeads = _dbContext.ProfileFans.Where(pf =>
pf.Fan.SNUrl.HasValue &&
pf.Activities.Any(fa => whiteList.Contains(fa.ActivityId)));
If you want the JOINs as well, you may want to look into .Include(), but from your original SQL query you seem like you're not going to actually need the contents of the joined tables.

Count child matches in linq Entity Framework

I try to count the number of child elements for each parent where the parent id is in a list if ints. But the count is not correct. Is it not possible to make a query like this? What is the correct way of doing this?
List<int> ids = [1, 2, 3];
var counts = (from d in db.Parent where ids.Contains(d.Id) select d.Child.Count()).ToList();
Assuming Child is a collection, because you are attempting to count it.
Try the following:
var counts = db.Parent.Where(x => ids.Contains(x.Id)).SelectMany(x => x.Child).Count();
"Count" will work on an IEnumerable. However it seems you are trying to work with a collection of IEnumerables. In these situations use "SelectMany" so that all the resulting collections are joined into one single collection.
The query does exact what I want, sorry for that. My problem was that the ids list was not sorted and that somehow made the query to not sort the output as the ids list was sorted. By sort the ids list (ids.Orderby(id)) this question was solved.
A list of counts and nothing else may offer sufficient information, but often some information on the containing entity will be useful (if only to prevent confusion):
List<int> ids = [1, 2, 3];
var counts = (from d in db.Parent where ids.Contains(d.Id)
select new
{
Parent = d.Name,
ChildCount = d.Child.Count()
}).ToList();

How to get a list which contains at least all the values of another list?

I have the situation where a list must contains at least the values of another list. So imagine we have list A with values 1, 2, 3. This is the list with the required values.
List B has the values 1, 5, 6, 7
List C has the values 1, 2, 3, 4, 7
List D has the values 2, 5, 6
In this situation I only want List C, since this is the only list which contains the values 1, 2 end 3.
I've tried this, but this doesn't work since it is always true:
query = from doc in query
let tagIds = from t in doc.Tags select t.Id
where parameters.TagIds.Except(tagIds).Count() <= parameters.TagIds.Count()
select doc;
And when using this:
query = from doc in query
let tagIds = from t in doc.Tags select t.Id
where !parameters.TagIds.Except(tagIds).Any<int>()
select doc;
I only get the lists where the list matches exactly the 'required' list.
My question is, how can I solve my situation in a Linq 2 SQL query?
Try
var query = from doc in query
let tagIds = from t in doc.Tags select t.Id
where parameters.All(p => tagIds.Contains(p))
select doc;
Try this link
Does .NET have a way to check if List a contains all items in List b?
here you can run the same above method in all available lists.
public static bool ContainsAllItems(List<T> a, List<T> b)
{
return !b.Except(a).Any();
}
This checks whether there are any elements in b which aren't in a - and then inverts the result.

Categories

Resources