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().
Related
I need help with filtering list data in c#.
I got 3 class named Product.cs, Storage.cs and Inventory.cs.
public class Storage{
string StorageId;
string Name;
}
public class Inventory{
string InventoryId;
string StorageId;
string ProductId;
}
I got the filled List<Storage> mStorages, List<Product> mProduct and List<Inventory> mInventories.
I have trouble to print mStorages that contain with specific productId that only can be obtained from mInventories.
So, I tried this:
List<Storage> mFilteredStorage;
for(int i=0;i<mStorages.Count;i++){
if(mStorages[i] contain (productId from inventories)){
mFilteredStorage.add(mstorages[i]);
}
So I can get mFilteredStorage that contains specific product from inventories. (in inventories there are lot of product id).
What should I do to get that filteredStorage? I tried to use list.contains() but it only return true and at last there are duplicated storage at mFilteredStorage.
Really need your help guys. Thanks in advance.
I suggest you to read about lambda-expressions, that is what you are looking for.
mFilteredStorage.AddRange(mStorages.Where(storage => inventories.Any(inventory => inventory.productId == storage.productId)).ToList());
This returns you a list with your filtered conditions. So right after Where you iterate over each item in your list, I called this item storage. (you can name those what ever you want to) Then we iterate over your object inventories with another lambda expression. This, the second lambda expression, returns either true if any of inventories's productIds match the productId of the current iterating object of mStorages or false if they don't match.
So you once the productIds match you can imagine the code like the following:
mStorages.Where(storage => true);
And once the result of the second lambda expression is true, storage will be added to the IEnumerable you will get as a result of the Where method.
Since we get an IEnumerable as return, but we want to add those Storage objects to mFilteredStorage, I convert the IEnumerable to a list, by:
/*(the return object we get from the `Where` method)*/.ToList();
You can use LINQ to accomplish your goal. Since Storage has no ProductId, the query will match by StorageId.
var filteredStoragesQry =
from storage in mStorages
where inventories.Any(inventory => inventory.StorageId == storage.StorageId)
select storage;
mFilteredStorages = filteredStoragesQry.ToList();
This query is for LINQ to objects, but it will also work in Entity Framework, when you replace mStorages and inventories by the respective DbSet objects from the context.
mStorages.Join(mInventories, x => x.StorageId, y => y.StorageId, (x, y) => new { Storage = x, ProductId = y.ProductId})
.Where(z => z.ProductId == "specificProductId").Select(z => z.Storage).ToList()
I ended with this code.
mFilteredStorage = tempStorage.GroupBy(s => s.Id).Select(group => group.First()).ToList()
This code is what I want to show.
//This works, but seems incorrect to me
Object selection = db.ExampleTable
.Where(s => s.Id == id)
.Select(s => new { s.Id, s.PropIWantToShow })
.SingleOrDefault();
//This seems correct, but does not work
Object selection = db.ExampleTable
.SingleOrDefault(s => s.Id == id)
.Select(s => new { s.Id, s.PropIWantToShow });
db is our Entity Framework data context.
My goal is to select a single entry matching the provided id in ExampleTable. If an entry is not found, this is to return null. However, EF doesn't seem to let me select a single object and then only return specific properties. How do I accomplish this or is the first example I provided correct?
I did check this question:
select properties of entity ef linq:
Unfortunately you cannot conditionally load properties of related entity - you either load whole door entity, or don't include that entity.
But the answer just doesn't seem right, but obviously "seems" is a very weak statement.
Your first method is correct:
//This works, but seems incorrect to me
Object selection = db.ExampleTable
.Where(s => s.Id == id)
.Select(s => new { s.Id, s.PropIWantToShow })
.SingleOrDefault();
Your second method gets you a single object, not an IQueryable<T> object that LINQ would work with. If you want to convert from one type of object to another, that isn't a LINQ thing. You can still, but it'll be more convoluted. Something like:
var selection =...;
var newselection=new { Id=selection.Id, PropIWantToShow=selection.PropIWantToShow };
but this is very bad because you DID retrieve the entire object from the DB, and then just threw away most of it. Your first method only returns 2 fields from the DB.
If you want your function to return null if condition doesn't match then use FirstorDefault() instead of SingleorDefalut(). So if you want to match an id and return an object then do it like this :
return db.ExampleTable.FirstorDefault(c=>c.Id == id);
I'm trying to fetch first element from the collection like this
List<Entity> data = session.Query<Entity>()
.Fetch(x => x.Photos.First())
.ToList();
and I'm getting this error.
A fetch request must be a simple member access expression; '[100002]' is a SubQueryExpression instead. Parameter name: relatedObjectSelector.
Now I'm using .Fetch(x => x.Photos.First()) cause I know that first element will always be populated, and it is. I do need just first element from the collection to reduce loading time, so this is exact solution I need, but I'm getting this error.
Fetch will fetch the entire collection, you can't tell it to just fetch the first element using "fetch", however you can probably get the desired effect using projections, or something like:
var subQ = QueryOver.Of<Entity>()
.SelectList(x => x.SelectMin(y => y.Photos)); // sub query selecting min photo id from entity
List<Photo> data = session.QueryOver<Photo>()
.Fetch(x => x.Entity).Eager // eager load the entity
.WithSubquery.WhereProperty(x => x.Id).In(subQ) // restrict the photo to those that are the first ones for the entity
.List() // execute query from database
.ToList(); // convert to List
Although I'm not sure why you'd want a List instead of IList.. generally it's preferable to use the interface
List<Entity> data = session.Query<Entity>()
.Fetch(x=>x.Photos.FirstOrDefualt())//here You need get only first element
.ToList();
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.
I am trying to find a linq query so I can write it in an if statement.
Pseudo code:
IDList is a list of ints List< int >
if (IDList.Contains (Object.Id)) Do something
but I can't seem to work out what need.
In none-linq this works:
foreach(int id in IDList )
{
if (id == Object.Id)
break;
}
but I want it as one line if possible.
I first tried this:
IDList.Contains(Object.Id);
but this throws a compile error
I'm wondering should it be one of these two?
IDList.Any(id => id == Object.Id)
or
IDList.Exists(id => id == Object.Id);
I don't completely understand how the lambdas and things work or the difference between andy and exists so I'm not sure if I'm along the wrong line?
You can simply do this:
if (MyList.Any(c => c.Id == MyObject.Id)) { }
Assuming that MyList is an IEnumerable<T> (or anything that derives from IEnumerable<T>) where T is an object that has a property named Id of the same type of the property Id on the MyObject instance.
IDList.Any(id => id == Object.Id)
Is ok, it will return you true if at least one element, that satisfies your predicate, exists.