Whenever i am changing an Entity Object reference changes are reflected to all other previous Objects that point to the same Entity. example:
var menu = menuRepo.FindByByIdAsync(12);
var menu1 = menuRepo.FindByByIdAsync(12);
menu.Name = "Name";
Console.WriteLine(menu.Name+ " "+ menu1.Name);
At this point if i run the code snippet both menu and menu1 are changed.
Is this happening because of the Entity's Proxies? I dont really understand it. If those two Objects where Class Objects they would have different names...how is this possible?
EDIT
Even stranger is the Orderby scenario i have tried...
var menu = menuRepo.FindById(1);
menu.MenuItems.OrderBy(m => m.OrderField).ToList();
these 2 lines actually order the items collection inside the menu Object.
I dont even have to set them...???
menu.MenuItems = menu.MenuItems.OrderBy(m => m.OrderField).ToList();
EF keeps only one instance of the same object in its context; FindByIdAsync retrieve the item having Id = 12 and set a reference of it in the context. The second time you call FindByIdAsync it returns a reference from the context to the same object. So that is why when you change the property in the first object the corresponding property in the second object is changed as well.
OrderBy dosen't return the ordered collection itself; the returned value is an object that stores all the information that is required to perform the sort.
The sorting is not executed until the object is enumerated either by calling its GetEnumerator method directly or by using foreach.
menu.MenuItems.OrderBy(m => m.OrderField)
dosen't execute any sort
menu.MenuItems.OrderBy(m => m.OrderField).ToList();
execute the sort because ToList() is invoked
Related
I'm trying to create a single instance of a model in my Db using Entity Core. The way I want it to work is, if the entry in the Db does not exist than make one. Instead of writing a getter method to do the work, is it possible to have Entity Core generate me a blank entry to work with and the save back?
I tried using FirstOrDefault to no avail.
Here is some sample code:
using (var context = new SearchTermInformationContext())
{
// this very first line should return me the single instance or create one if it doesnt exist.
var searchTermInfo = context.SearchTermInformation.FirstOrDefault();
searchTermInfo.num_search_terms += numSearchTerms;
searchTermInfo.offset = offset;
searchTermInfo.last_updated += (DateTime.UtcNow.Ticks / TimeSpan.TicksPerMillisecond).ToString();
await context.SaveChangesAsync(ct);
}
FirstOrDefault() grabs the first element of an IEnumerable, and if the sequence is empty it returns the default value for that type. Since an Entity is always going to be a class, the default "value" for any class is null. There is no way to my knowledge to change this behavior. If you want this behavior, you will have to implement it yourself by creating a new instance of your type, filling in the fields, and performing an insert through your context. If you want to get really fancy, you might be able to make an extension method on DbSet<T> to perform an add of a blank instance and return the attached entity without saving changes.
I want a copy of an ObservableCollection by filtering it with some condition. Please help me.
I treid the following code:
ObservableCollection<YourEntity> clonedCollection = new ObservableCollection<YourEntity>(clonedList);
This is ok, but need copy with condition (new object filtered from the old one). need to copy some particular data from clonedList
Use a linq query to filer the elements in the source collection.
A .Where() query does it pretty good. You can use .Select() or any other query too.
ObservableCollection<YourEntity> cloned = new ObservableCollection<YourEntity>(source.Where(e => e.IsSomeConditionFulfilled()));
Note that you do not clone the objects passing an IEnumerable to the constructor of the ObservableCollection - both collections cloned and source will reference the same objects. That means, if you change some YourEntity instance properties via the source collection (e. g. source.First().SomeProperty = SomeValue), and this object is also contained in the cloned collection (e. g. cloned.First() == source.First()), then those changes will be reflected there.
I have a strange thing happening with automapper.
Do someone have a clue why this code is returning a value for the InstitutionsImplantations field :
var result1 = new List<DataModel.Implantations>();
foreach (var c in collection)
{
DataModel.Implantations i = Mapper.Map<DataModel.Implantations>(c);
result1.Add(i);
}
var item1 = result1.Where(x => x.Nom == "Valdor").FirstOrDefault();
Console.WriteLine(item1.InstitutionsImplantations);
While this one (on the same collection), return null for InstitutionsImplantations :
var result2 = Mapper.Map<IEnumerable<DataModel.Implantations>>(collection);
var item2 = result2.Where(x => x.Nom == "Valdor").FirstOrDefault();
Console.WriteLine(item2.InstitutionsImplantations);
Facts :
The mapping done by autommaper on the IEnumerable is correct for the +/- first 300 items in the list, then after, some item collection have a "badly" mapped InstitutionsImplantations property.
InstitutionsImplantations property is an object "proxy" from a EF result.
do you have an idea why this is happening ?
Tx you !
Found the problem, using the automapper source code to see what was going on behind the scenes.
When automapper is processing the IEnumerable collection, its using a caching mechanism to avoid to have to remap an already mapped object that was present in the collection.
You would say, its fair, no reason to have the same object mapped to a different result.
But in my scenario, I forget to add that I was also using an AfterMap delegate at the mapping declaration.
In this AfterMap I was doing this (To avoid circular references problem) :
mappedItem.InstitutionsImplantations.Institution.InstitutionsImplantations = null;
This problem of this is that, I though that it was only impacting the result of the mapping (AfterMap delegate), and nothing else, but I was wrong it is also impacting the "Cache" being put in place !
This is not was I wanted, because in this case it did also impact all following mapping computing in the collection, using "Null" for the following mapped InstitutionsImplantations object, instead of brand new mapping.
My first solution was clean because the caching mechanism did not work between 2 "different" mapping.
And I didn't find an easy way to disable this collection caching mechanism inside automapper !
I add items to a list box like so:
foreach(myObject object in ListOfObjects)
{
mylistbox1.add(object);
}
foreach(myObject object in ListOfObjectsTwo)
{
mylistbox2.add(object);
}
Further on, I want to remove a couple of items given a specific condition. This is what I do:
foreach(myObject object in ListOfObjects3)
{
mylistbox1.items.remove(object);
mylistbox2.items.remove(object);
}
This only seems to work for mylistbox1 but not mylistbox2. When I debug, I can see that the item is there and that it has the exact same properties as the one I'm trying to remove. When I try to check if the listbox contains the item im trying to remove, it returns false.
I can't seem to make sense of it.
I c# all lists operation that are in some way required to compare objects use Equals or GetHashCode methods. In your case Equals and the default implementation wont check properties values it will only verify if the passed as argument object is in list so consider if you have the same instance in your list or just two different instances that happened to have the same properties. (the helpful VS option is make object id it will mark instance with a number)
If this is the case then you should consider overriding Equals method or find the instance that you want to delete with linq for example and pas that object to Remove method.
I have the following situation. I have a list of items which have an "Id". I have to search for an item with a specific id, modify its values and maintain the order of the collection. What would be the best way to do that?
var collection = <some_linq_query>
collection.Where(i=>i.Id=someId).FirstOrDefault().Property = "bla";
// now collection should be the same but the item updated.
The call to Where does not modify the original LINQ query stored in collection in any way. Instead it creates a new IEnumerable<T> where is a subset of the original query. The subset will have the same relative ordering as the original set in collection
The only way this could cause a problem is if the value collection is a LINQ where which has a Where clause, or is otherwise filtered, base on the value of Property. If that is the case and you want to preserve the order force collection into a non-lazy evaluated structure via .ToList.
collection = collection.ToList();
As long as the objects in the collection are mutable, your code should work fine.
By the way, FirstOrDefault takes an optional filter parameter, so you can write collection.FirstOrDefault(i => i.Id == someId).