I have the following variable,
var actionIds = formFields.Select(x => x.GridDefinition.Actions.ToList().Select(y =>y.DFActionID).ToList()).ToList();
It is giving me the result as List<List<int> but I want the result as List<int>
How should I go about it?
Later I need to check IDs from the above list with a single ID like the below.
var removedFormFieldsActions = existingFormFieldsActions.Where(x => !actionIds.Contains(x.DFActionID));
Which is currently giving an error.
There are a couple of problems in your code. First of all, why convert Actions to a list if you are going to map each action right after that? So, the first fix is to remove that ToList() call:
var actionIds = formFields
.Select(x => x.GridDefinition.Actions.Select(y => y.DFActionID).ToList())
.ToList();
Then the second improvement comes, which stems from the fundamental question - what do you want to get in the end? Are all those items in all the separate lists the same, and should be placed into a single list? If so, then you need to use the SelectMany() operator, which, again, does not require the intermediate ToList() since the final ToList() will collect all the items anyway:
var actionIds = formFields
.SelectMany(x => x.GridDefinition.Actions.Select(y => y.DFActionID))
.ToList();
Related
epublic ActionResult ExistingPolicies()
{
if (Session["UserId"]==null)
{
return RedirectToAction("Login");
}
using(PMSDBContext dbo=new PMSDBContext())
{
List<Policy> viewpolicy = new List<Policy>();
var userid = Session["UserId"];
List<AddPolicy> policy= dbo.AddPolicies.Where(c => c.MobileNumber ==
(string)userid).ToList();
foreach(AddPolicy p in policy)
{
viewpolicy=dbo.Policies.Where(c => c.PolicyId ==p.PolicyId).ToList();
}
Session["Count"] = policy.Count;
return View(viewpolicy);
}
}
Here the policy list clearly has 2 items.But when I iterate through foreach,the viewpolicy list only takes the last item as its value.If break is used,it takes only the first item.How to store both items in viewpolicy list??
Regards
Surya.
You can iterate through policies and add them by one to list with Add, but I would say that often (not always, though) better option would be to just retrieve the whole list from DB in one query. Without knowing your entities you can do at least something like that:
List<AddPolicy> policy = ...
viewpolicy = dbo.Policies
.Where(c => policy.Select(p => p.PolicyId).Contains(c.PolicyId))
.ToList();
But if you have correctly set up entities relations, you should be able to do something like this:
var viewpolicy = dbo.AddPolicies
.Where(c => c.MobileNumber == (string)userid)
.Select(p => p.Policy) //guessing name here, also can be .SelectMany(p => p.Policy)
.ToList();
Of course; instead of adding to the list, you replace it with a whole new one on each pass of the loop:
viewpolicy=dbo.Policies.Where(c => c.PolicyId ==p.PolicyId).ToList()
This code above will search all the policies for the policy with that ID, turn it into a new List and assign to the viewpolicy variable. You never actually add anything to a list with this way, you just make new lists all the time and overwrite the old one with the latest list
Perhaps you need something like this:
viewpolicy.Add(dbo.Policies.Single(c => c.PolicyId ==p.PolicyId));
This has a list, finds one policy by its ID number (for which there should be only one policy, right? It's an ID so I figured it's unique..) and adds it to the list
You could use a Where and skip the loop entirely if you wanted:
viewpolicy=dbo.Policies.Where(c => policy.Any(p => c.PolicyId == p.PolicyId)).ToList();
Do not do this in a loop, it doesn't need it. It works by asking LINQ to do the looping for you. It should be converted to an IN query and run by the DB, so generally more performant than dragging the policies out one by one (via id). If the ORM didn't understand how to make it into SQL you can simplify things for it by extracting the ids to an int collection:
viewpolicy=dbo.Policies.Where(c => policy.Select(p => p.PolicyId).Any(id => c.PolicyId == id)).ToList();
Final point, I recommend you name your "collections of things" with a plural. You have a List<Policy> viewpolicy - this is a list that contains multiple policies so really we should call it viewPolicies. Same for the list of AddPolicy. It makes code read more nicely if things that are collections/lists/arrays are named in the plural
Something like:
viewpolicy.AddRange(dbo.Policies.Where(c => c.PolicyId ==p.PolicyId));
Given a List<string> How to return all records in an entity that has a field containing one or more words from the list.
I tried the below which does not work and I'm starting to go around in circles a bit:
List<string> searchwords = new List<string>() {"word1","word2"};
var results = context.activities
.Where(a => a.Title.Contains(searchwords.Any().ToString())).ToList();
The problem with your current code:
var results = context.activities.Where(a =>
a.Title.Contains(searchwords.Any().ToString())).ToList();
is that you have your needle and haystack backwards. The fact that you needed to call .ToString() on Any() should have tipped you off. Any() returns a bool, which you're casting to a string, so you're just checking whether Title contains the string "True". Definitely not what you want. You want something closer to:
var results = context.activities
.Where(a => searchwords.Any(searchWord => a.Title.Contains(searchWord)));
I am stuck on a LINQ query where I have being trying to return a list records from an SQL Table using EntityFramework 6, instead of getting that list, I keep end up getting an IEnumerable<string[]>.
This is what I have made to get IEnumerable<string[]>. I have an column in the table that needs to be split and then I test to see if a list contains those strings : The value in the table column columnOne can be something like this "a-b" or "b-c" etc, hence the need to use this s.columnOne.Split('-')
list<string> checkList = new list<string>();
checkList.add("a")
checkList.add("b")
checkList.add("c")
List<Foo> fooList = dbContext.Foos.ToList();
IEnumerable<string[]> items = fooList.Select(s => s.columnOne.Split('-'));
var result = items.SelectMany(x => x)
.Where(s => checkList.Contains(s)).ToList();
The above works as it should, but in the end it returns a list of string, which is not what I need.
I tried this below:
List<Foo> fooList = dbContext.Foos.ToList();
var test = fooList.Where(s => s.columnOne.Split('-'));
And this is where I run into the error and can go no further as I am ultimately trying to return a list of <Foo>, not <string>
Now I know that the Where clause needs to return a bool value such as fooList.Where(s => s.columnOne == "someString");, but I am at a loss as to how to go about structuring the LINQ query to get the results I am trying to get.
Any shove in the right direction would be great.
The where clause needs to contain the check against the checkList
var test = fooList.Where(foo => foo.columnOne.Split('-').Any(str => checkList.Contains(str)));
dbContext.Foos
.ToList()
.Where(foo => foo.columnOne.Split('-')
.Any(x => checkList.Contains(x))
I hope you don't ever have very many Foos because that ToList function will read them all into memory. You'll need that, though, because I don't think Linq can understand how to translate that where statement. There are a few ways to get around that, if it's a problem to you.
Also, consider using a Set<string> instead of a List<string> for your checklist variable, as it'll perform better for membership checks like this one.
I think what I need is relatively simple but every example I Google just returns results using First(), which I'm already doing. Here is my expression:
var options = configData.AsEnumerable().GroupBy(row => row["myColumn"]).Select(grp => grp.First());
What I need is only ONE column from the grp portion and to be able to suffix .ToList() on there without an error. As it stands I receive 4 columns, but only need a specific one, kind of like if this (grp => grp["myColumn"]), didn't result in error the Error 153 Cannot apply indexing with [] to an expression of type 'System.Linq.IGrouping<object,System.Data.DataRow>'
Also, Key does not work in the grouping portion as these results are from a DataTable object. See here - >
If you want only the keys, you can use
var options = configData.AsEnumerable().Select(row=>row["myColumn"]).Distinct();
I think that this is what you want:
configData.AsEnumerable()
.GroupBy(r => r["myColumn"])
.Select(g => new
{
myColumnValue = g.Key,
myColumnItems = g.Select(r => r["OtherColumn"]).ToList()
});
Do you understand how/what this does though? Try it out and inspect the resulting IEnumerable. I'm not sure you have a perfect understanding on how GroupBy works but take your time with above example.
See this part:
new
{
myColumnValue = g.Key,
myColumnItems = g.Select(r => r["OtherColumn"]).ToList()
}
This creates an anonymous type which outputs the values of "OtherColumn" column into a list grouped by "myColumn" where value of "myColumn" is in the myColumnValue property.
I'm not sure this answers your question but it looks like this is what you want.
The variable g is of the type IGrouping<object, DataRow>, it's not DataRow. The IGrouping interface is designed to provide a list of DataRow's grouped by object values - it does not produce a flat list, if it did then it would just be a Sort, not GroupBy.
Just specify the field you want after your call to First() e.g.
.Select(grp => grp.FirstOrDefault()["MyFieldName"]);
This will take the first record from the grouping and select the specified field from that record.
I have list of objects of a class for example:
class MyClass
{
string id,
string name,
string lastname
}
so for example: List<MyClass> myClassList;
and also I have list of string of some ids, so for example:
List<string> myIdList;
Now I am looking for a way to have a method that accept these two as paramets and returns me a List<MyClass> of the objects that their id is the same as what we have in myIdList.
NOTE: Always the bigger list is myClassList and always myIdList is a smaller subset of that.
How can we find this intersection?
So you're looking to find all the elements in myClassList where myIdList contains the ID? That suggests:
var query = myClassList.Where(c => myIdList.Contains(c.id));
Note that if you could use a HashSet<string> instead of a List<string>, each Contains test will potentially be more efficient - certainly if your list of IDs grows large. (If the list of IDs is tiny, there may well be very little difference at all.)
It's important to consider the difference between a join and the above approach in the face of duplicate elements in either myClassList or myIdList. A join will yield every matching pair - the above will yield either 0 or 1 element per item in myClassList.
Which of those you want is up to you.
EDIT: If you're talking to a database, it would be best if you didn't use a List<T> for the entities in the first place - unless you need them for something else, it would be much more sensible to do the query in the database than fetching all the data and then performing the query locally.
That isn't strictly an intersection (unless the ids are unique), but you can simply use Contains, i.e.
var sublist = myClassList.Where(x => myIdList.Contains(x.id));
You will, however, get significantly better performance if you create a HashSet<T> first:
var hash = new HashSet<string>(myIdList);
var sublist = myClassList.Where(x => hash.Contains(x.id));
You can use a join between the two lists:
return myClassList.Join(
myIdList,
item => item.Id,
id => id,
(item, id) => item)
.ToList();
It is kind of intersection between two list so read it like i want something from one list that is present in second list. Here ToList() part executing the query simultaneouly.
var lst = myClassList.Where(x => myIdList.Contains(x.id)).ToList();
you have to use below mentioned code
var samedata=myClassList.where(p=>p.myIdList.Any(q=>q==p.id))
myClassList.Where(x => myIdList.Contains(x.id));
Try
List<MyClass> GetMatchingObjects(List<MyClass> classList, List<string> idList)
{
return classList.Where(myClass => idList.Any(x => myClass.id == x)).ToList();
}
var q = myClassList.Where(x => myIdList.Contains(x.id));