Using linq to check property against one of multiple possible values - c#

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 ...

Related

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

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)

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.

How to transfer 2 Enumerable collections to 1 ObservableCollectionsList?

This is a complete Newbie question and I understand but how do I transfer these two distinct Enumerable collections to a single ObservableCollections?
var distinctLine1 = (from z in list
orderby z.ItemLine1
select z.ItemLine1).Distinct();
var distinctLine2 = (from z in list
orderby z.ItemLine2
select z.ItemLine2).Distinct();
foreach (var item in distinctLine1)
{
}
Sorry did change ObservableCollectionsList to ObservableCollections
ItemLine1 and ItemLine2 are both strings
I suppose you could probabl also call Distinct on union to exclude possible duplicates.
var union = distinctLine1.Union(distinctLine2).Distinct();
Or just
var union = distinctLine1.Union(distinctLine2);
And then simply create the target collection with ObservableCollection Constructor (IEnumerable):
var result = new ObservableCollection<string>(union);

grouping and counting in linq-to-sql

I have the following query that receives a list of IDs and I want to do a count. There's also an object model CountModel that holds the counts with each property defined as an int.
public class GetCountByStatus(List<int> TheIDs)
{
...using MyDC...
var CountData = (from d in MyDC.Data
where TheIDs.Contains(d.ID)
group d by d.Status into statusgroup
select new CountModel()
{
CountStatus1 = (from g in statusgroup
where g.Status == 1
select g).Count(),
CountStatus2 = (from g in statusgroup
where g.Status == 2
select g).Count(),
CountStatusN = ....
}).Single();
If for instance there are no elements with status N, will this code crash or will the count be 0 for CountStatusN ? Is this the best way to do what I want?
Thanks.
I would go for a dictionary instead, try something like this:
var countData = MyDC.Data.Where(y => TheIDs.Contains(y.ID))
.GroupBy(y => y.Status).ToDictionary(y => y.Key, y => y.Count());
I haven't tried it my self and not written the code in VS, but I think that is almost how you do can do it. That will give you a dictionary where the key is the status and the value is the count of that status.
Defining a model with properties named SomethingX is not very flexible. That means you have to go in an change the model when there is a new status. Keeping the data in the dictionary instead will save you from that.
Count() will always return an integer, which is 0 if there are no elements with the given status. Therefore CountStatusN will always be an integer as well.

Entity Framework - Join to a List

I need to retrieve a list of entities from my database that matches a list of items in a plain list (not EF). Is this possible with Entity Framework 4.1?
Example:
var list = new List<string> { "abc", "def", "ghi" };
var items = from i in context.Items
where list.Contains(i.Name)
select i;
This works great to return rows that match one property, but I actually have a more complex property:
var list = new List<Tuple<string, string>>
{
new Tuple<string,string>("abc", "123"),
new Tuple<string,string>("def", "456")
};
// i need to write a query something like this:
var items = from i in context.Items
where list.Contains(new Tuple<string,string>(i.Name, i.Type))
select i;
I know that is not valid because it will say it needs to be a primitive type, but is there any way to do what I'm trying to accomplish or will I need to resort to a stored procedure?
You have a few options:
1) You could, of course, write a stored procedure to do what you need and call it.
2) You could read the table into memory and then query the in memory list...that way you don't have to use primitives:
var items = from i in context.Items.ToList()
where list.Contains(new Tuple<string, string>(i.Name, i.Type))
select i;
3) You could also convert your query to use primitives to achieve the same goal:
var items = from i in context.Items
join l in list
on new { i.Name, i.Type } equals
new { Name = l.Item1, Type = l.Item2 }
select i;
I would go with the second option as long as the table isn't extremely large. Otherwise, go with the first.
You need to break it down to sub-properties. For example, something like (this might not compile, i'm not able to test at the moment, but it should give you something to work with):
var items = from i in context.Items
where list.Select(x => x.Item1).Contains(i.Name)
&& list.Select(x => x.Item2).Contains(i.Type)
select i;
You have to think about what the resulting SQL would look like, this would be difficult to do directly in SQL.
My suggestion would be you split out one field of the tuples and use this to cut down the results list, get back the query result then filter again to match one of the tuples e.g.
var list = new List<string> { "abc", "def" };
var list2 = new List<Tuple<string, string>>
{
new Tuple<string,string>("abc", "123"),
new Tuple<string,string>("def", "456")
};
var items = (from i in context.Items
where list.Contains(i.Name)
select i)
.AsEnumerable()
.Where(i => list2.Any(j => j.val1 == i.Name && j.val2 == i.Type);

Categories

Resources