I have an DbQuery and I want to fill another list with my DbQuery Item with some conditions like:
var carsList= DbContext.Cars.Where(e=> e.brand == brand);
var myFiltredcarList = new List<Car>();
foreach(var car in carsList)
{
//add items in list according to a condition
myFiltredcarList.Add(car);
}
I want to now if is possible to do something like :
myFiltredcarList.Include("Brands");
I cannot use my myFiltredcarList as List, I want to keep my carsList bidings to do an include in my filtred list(myFiltredcarList)
Is it possible ?
If it's what I need to change?
It's not possible.
First off, the Include method is defined on IQueryable<T>, and second it works only on LINQ To Entities queries, which your list apparently is not.
The only way could be if you can embed the filtering condition into original query like this
var myFiltredcarList= DbContext.Cars
.Include("Brands")
.Where(e => e.brand == brand && some condition)
.ToList();
Related
I have collection which have other collection in it. And I need some elegant solution to the following:
I need to filter the first collection by it is inner collection. So in the first collection will remain only the objects that have nested collection which answer some filter. Next i want in the filtered first object to have inner collection filtered by the same filter.
Check the first level filtering:
collectionOne = collectionOne.Where(a => a.collectionTwo.Any(g => !string.IsNullOrEmpty(g.Value) && g.Value.Contains(stringValue)));
This way i will filter the first collection, but the inner one will be still not filtered. I want to filter the inner collection with the same filter for each object in the first one :) I can do this with some loop (afte the first filter), but maybe there is better way?
Possible solution:
foreach(var item in collectionOne)
{
item.collectionTwo = ... same filter
}
P.S. The reason I ask this is because there is also a switch case about the filter itself. So I will have to copy-paste the solution a couple times with different filter only.
That` why i do not prefer the loop.
Other Solution is to create Func which will be re-used in .Where clause, but this is also not efficient because each filter is kind of simple.
If understand it correctly, what you're looking for is:
collectionOne = collectionOne
.Where(filter)
.Select(item =>
{
item.collectionTwo = collectionTwo.Where(filter);
return item;
});
And, if you just want to select and not modify the items:
collectionOne = collectionOne
.Where(filter)
.Select(item =>
new X{
collectionTwo = collectionTwo.Where(filter),
// copy all other fields
});
I am trying to create a simple search function for my application. I am using Linq's .Find() method to search through a list of objects. It all works very well, the only problem I'm currently having is that I only get the first result. I know for a fact that there are more than one results to be had, but I only get one. Here is my code:
case 5: {
//Search for Price
Product searchResult = tempList.Find(x => x.getPrice() == searchPrice);
if (searchResult != null) {
//Present Result
searchTable.Rows.Add(convertIDValue(searchResult.getProductID()), searchResult.getTitle(), searchResult.getYear(), searchResult.getAmount(), searchResult.getPrice());
}
else {
MessageBox.Show("No product with that price", "0 results");
}
break;
}
I thought I could change Product searchResult into List<Product> searchResults in order to get a list of Products, then loop through that list. But that gave me an error saying:
Cannot implicitly convert type '.Product' to 'System.Collections.Generic.List<.Product>
Is there any way to get Linq's .Find() to return multiple results?
Use Where() and ToList() to get all objects, matching the condition into a List
replace
Product searchResult = tempList.Find(x => x.getPrice() == searchPrice);
with
List<Product> searchResult = tempList.Where(x => x.getPrice() == searchPrice).ToList();
There is a FindAll method for that purpose:
List<Product> products = tempList.FindAll(x => x.getPrice() == searchPrice);
Find() searches for an element that matches the conditions defined by the specified predicate, and returns the first occurrence within the entire List.
You need to use FindAll() instead.
Microsoft explains the "Find()" method :"Searches for an element that matches the conditions defined by the specified predicate, and returns the first occurrence within the entire List."
I would suggest you to use this Where() method from Linq extension.
Don't forget to import "using System.Linq" in your current class.
Product searchResult =
means you are declaring one element. The thing you need is a collection of products, like:
IEnumerable<product> searchResult =
The easiest way to do it is to change Find() to where():
IEnumerable<product> searchResult = tempList.Where(x => x.getPrice() == searchPrice);
this will create some collection of product's. It will be easier to maintain as a list, so:
list<product> searchResult = tempList.Where(x => x.getPrice() == searchPrice).toList();
Read about IEnumerable interface :)
I am trying to fetch an option using the SingleOrDefault Linq to SQL method.
var po = repository.Context.AsQueryable<Option>().SingleOrDefault(o => o.Option.Id == sp.Options // sp.Options is a collection);
The problem is that inside the SingleOrDefault method I am comparing p.Option.Id == a collection. What I want is to select the option from sp.Options that matches the o.Option.Id. How can I do that?
UPDATE:
One thing I should have mentioned that the sp.Options is a different class than the Option class. sp.Options is SPOptions class so I cannot pass it inside the contains method.
Take a look at Contains.
repository.Context.AsQueryable<Option>().SingleOrDefault(o => sp.Options.Contains(o.Option.Id));
If Options is not a collection of the class of Option.Id, you can use the Any method with your comparison logic in it as follow :
repository.Context.AsQueryable<Option>().SingleOrDefault(o => sp.Options.Any(opts => opts.Something == o.Option.Id));
Search using Contains (sp.Options.Contains(o.Option.Id)) like:
var po = repository.Context.AsQueryable<Option>()
.SingleOrDefault(o => sp.Options.Contains(o.Option.Id));
If members of sp.Options are different from Id then you can do:
var po = repository.Context.AsQueryable<Option>()
.SingleOrDefault(o => sp.Options.Any(r=> r.Id == o.Option.Id));
or
var po = repository.Context.AsQueryable<Option>()
.SingleOrDefault(o => sp.Options.Select(r=> r.Id).Contains(o.Option.Id));
Assuming Id is the field in sp.Options elements that you want to compare with.
Based on your question it seems you're expecting to have a single match between those two option sets, correct ?
If so, I'd suggest you to write it as:
var po = repository.Context.AsQueryable().Where(o => sp.Options.Any(item=>item.id == o.Option.Id)).SingleOrDefault();
Is something like this possible? I am getting the below error.
db.SomeTable.Add(new SomeTable()
{
GuidId = Guid.NewGuid(),
Name = db.AnotherTable.Select(x => x.Name.Where(x.Id == localVariable.Id))
}
);
db.SaveChanges();
Unknown Select(?) of System Data Entity DbSet
Select returns an IEnumerable, not an individual record. You would needed to add a .First() call to grab just one record. Entity Framework thinks you're trying to put a list into a single field.
Furthermore, your use of Where() is incorrect. Where also returns an IEnumerable, and can only be applied on to an IEnumerable. Think of it as a way to filter a list.
Here's how to do what I think you're asking for:
Name = db.AnotherTable.First(x => x.id == someId).Name
I think what you want is this:
Name = db.AnotherTable
.First(x => x.Id == localVariable.Id)
.Name;
The steps of this are:
Go into list of items in AnotherTable
Find the first item where the Id of the item is equal to localVariable.Id
Set your variable equal to the Name property of the item you found
You can also use FirstOrDefault(), Single(), and SingleOrDefault().
If I try:
List<Student> students = new List<Student>();
List<Group> Groups = new List<Group>();
Groups = students.Remove(f => f.StudentID.Equals(studentID));
I get an error on this line: f => f.StudentID.Equals(studentID)
I am having difficulty from my previous posts here https://stackoverflow.com/questions/10116685/linq-deleted-users-still-associated-with-groups and here Delete method in WCF
So I thought maybe I could delete the students contained within groups but I get an error Cannot convert lambda expression to type Student because it is not a delegate type.
Just a quick up date as to what I am trying to do, lets say student A can belong to multiple Groups. Then if I delete that student the student should no longer list any groups. But it does. However if I search lets say Group Computing the student isnt there. Only seems to be when I take the student and search which groups he belongs to (even if he is deleted) it returns the group I originally added him to. THIS SHOULDNT HAPPEN ARGHH
If you are trying to pass in the predicate, you have to use the RemoveAll method. Remove method takes in a single element
var numRemoved = students.RemoveAll(f => f.StudentID == studentID);
Also the RemoveAll method doesn't return the "updated" list, it updates the list. So students would be updated list i.e. it would not have students with StudentID == studentID.
If you want to preserve the students as is, copy the elements to a new list
var newStudentList = new List<Student>(students);
and then filter that list
P.S. The common objects in both list are same i.e. if an object is updated in one list, it would get updated in the second list too. If a second copy is needed, deep cloning has to be implemented. This is just two lists from same pool of objects.
var numRemoved = newStudentList.RemoveAll(f => f.StudentID == studentID);
With your updates, it seems you are looking for
students.RemoveAll(s => s.StudentID == studentID);
Groups.ForEach(g => g.Groupsz.RemoveAll(gs => gs.StudentID == studentID));
Try with RemoveAll...........
List<T>.Remove() has a return type of bool. So you're not going to get a List<Group> from List<Student>.Remove().
You can use var removed = students.RemoveAll(f => f.StudentID.Equals(studentID)); to get a list of which students were removed from list.
But you'll need to do a little more to get that list of students to be a List<Group>. There is not enough information in your question to tell if a conversion possibility exists.