How to "dispose" an EntityManager - breeze

We've taken the approach of creating a new EntityManager each time we load an view for editing a record (to support a unit-of-work pattern).
Is there anything special we need to do to allow the EntityManager to be garbage collected? I believe we are releasing all references to the manager but Chrome's "Take Heap Snapshot" tool doesn't show the EntityManager (or any entities) being deleted when we leave our view.
I see that each entity's entityAspect.entityManager holds a reference to the manager. Does that prevent everything from getting garbage collected?

It appears that calling entityManager.clear() is required to detach all entities from the manager which then allows everything to get garbage collected.

Related

Is Dart smart enough to automatically dispose variables?

Is Dart smart enough to automatically dispose variables? for instance in the following code
class Foo {
final streamController = StreamController<int>.broadcast();
final textController = TextEditingController();
}
Must I manually call textController.dispose() and streamController.close()
Dart is a garbage collected language. If an object cannot be accessed by any code any more, if it makes not difference to the program whether it exists or not, the value might eventually be garbage collected. That will necessarily be completely invisible to the program, it's just a memory optimization to not keep things around which makes no difference.
Whether an object is actually unreachable/garbage-collectible depends on whether the program or the run-time system keeps a reachable reference to it, directly or indirectly.
Some objects are kept alive by the run-time system. For example, an open file needs to be remembered so that the system can close it and release the resource when the program ends, whether your code remembers it or not. In general, an allocated system resource should always be assumed to be alive in some way, and you need to dispose/close/cancel it to be sure it's released.
Dart does not try to guess whether one variable of an object is unreachable when the object itself is reachable. In the given example, if a Foo object instance is reachable, then so is the values of its variables. (If there is literally no references to foo.streamController anywhere in the program, including through dynamic invocations, that variable might be optimized away by the compiler, but I wouldn't depend on it).
If there is no reference to a Foo object, then whether the values of the variables are garbage collected depends on whether there are other references to them. I'll assume you're not keeping them around yourself, so the question is whether they are remembered by the run-time system.
I can't speak for TextEditingController. I'm guessing it's a Flutter thing. I do not know whether it contains any system resources.
The stream controller is only kept alive as long as its stream or that stream's listeners.
If there are no current listeners on the controller, and no-one has stored foo.streamController.stream anywhere, there won't be any references to the controller.
Even if there are listeners, StreamSubscriptions, then if those subscriptions are not reachable, then the controller also isnt'.
(The one exception may be while a new event has recently been added to the controller, and a system timer has been set to deliver the event shortly later, but that's only for a very short while).

breeze memory management - pattern / practice?

I have an old SL4/ria app, which I am looking to replace with breeze. I have a question about memory use and caching. My app loads lists of Jobs (a typical user would have access to about 1,000 of these jobs). Additionally, there are quite a few lookup entity types. I want to make sure these are cached well client-side, but updated per session. When a user opens a job, it loads many more related entities (anywhere from 200 - 800 additional entities) which compose multiple matrix-style views for the jobs. A user can view the list of jobs, or navigate to view 1 job at a time.
I feel that I should be concerned with memory management, especially not knowing how browsers might deal with this. Originally I felt this should all be 1 EntityManager and I would detachEntities when user navigates away from a job, but I'm thinking this might benefit from multiple managers by intended lifetime. Or perhaps I should create a new dataservice & EntityManager each time the user navigates to a new hash '/#/' area, since comments on clear() seems to indicate that this would be faster? If I did this, I suppose I will be using pub/sub to notify other viewmodels of changes to entities? This seems complex and defeating some of the benefits of breeze as the context.
Any tips or thoughts about this would be greatly appreciated.
I think I understand the question. I think I would use a multi-manager approach:
Lookups Manager - holds once-per session reference (lookup) entities
JobsView Manager - "readonly" list of Jobs in support of the JobsView
JobEditor Manager - One per edit session.
The Lookups Manager maintains the canonical copy of reference entities. You can fill it once with a single call to server (see docs for how). This Lookups Manager will Breeze-export these reference entities to other managers which Breeze-import them as they are created. I am assuming that, while numerous and diverse, the total memory footprint of reference entities is pretty low ... low enough that you can afford to have more than one copy in multiple managers. There are more complicated solutions if that is NOT so. But let that be for now.
The JobsView Manager has the necessary reference entities for its display. If you only displayed a projection of the Jobs, it would not have Jobs in cache. You might have an array and key map instead. Let's keep it simple and assume that it has all the Jobs but not their related entities.
You never save changes with this manager! When editing or creating a Job, your app always fires up a "Job Editor" view with its own VM and JobEditor Manager. Again, you import the reference entities you need and, when editing an existing Job, you import the Job too.
I would take this approach anyway ... not just because of memory concerns. I like isolating my edit sessions into sandboxes. Eases cancellation. Gives me a clean way to store pending changes in browser storage so that the user won't lose his/her work if the app/browser goes down. Opens the door to editing several Jobs at the same time ... without worrying about mutually dependent entities-with-changes. It's a proven pattern that we've used forever in SL apps and should apply as well in JS apps.
When a Job edit succeeds, You have to tell the local client world about it. Lots of ways to do that. If the ONLY place that needs to know is the JobsView, you can hardcode a backchannel into the app. If you want to be more clever, you can have a central singleton service that raises events specifically about Job saving. The JobsView and each new JobEditor communicate with this service. And if you want to be hip, you use an in-process "Event Aggregator" (your pub/sub) for this purpose. I'd probably be using Durandal for this app anyway and it has an event aggregator in the box.
Honestly, it's not that complicated to use and importing/exporting entities among managers is a ... ahem ... breeze. Well worth it compared to refreshing the Jobs List every time you return to it (although you'll want a "refresh button" too because OTHER users could be adding/changing those Jobs). You retain plenty of Breeze benefits: querying, validation, change-tracking, batch saves, entity navigation (those reference lists work "for free" in Breeze).
As a refinement, I don't know that I would automatically destroy the JobEditor view/viewmodel/manager when I returned to the JobsView. In my experience, people often return to the same Job that they just left. I might hold on to a view so you could go back and forth quickly. But now I'm getting tricky.

Avoiding registered object buildup (memleak) in NSManagedObjectContext

I have a memory-intensive iOS app and I'm working on making sure that memory usage does not build up over time. My app has a "main" context that lives for the lifetime of the app, with other smaller contexts being spawned occasionally for background tasks.
One thing I have noticed is that NSManagedObjects appear to remain registered in the main context long-term and the only way to truly reclaim all the memory associated with pulling the objects from the DB is to call [NSManagedObjectContext reset].
This of course results in a nice drop in memory usage as all the registered objects from recently closed list views are properly ejected from memory, however it is annoying because you have just invalidated every object that was registered in that context that you still have a reference to (i.e. objects that are refered to by views that are still open), and you now need to re-fetch all the these objects from the database to avoid exceptions for accessing an invalidated object.
Is this the only way of flushing out the registered object set from an NSManagedObjectContext, or is there a better way that successfully ejects all the registered objects you no longer have references to, but doesn't invalidate all the NSManagedObjects that are still alive?
NSManagedObjectContext has an internal row cache, and the only way you can clear that out is by resetting the context. If you're actually experiencing memory issues, a few things that may help are:
Managed objects retain their related objects. If you have managed object A that's referenced by a relationship from some other managed object B, then object A will remain in memory even if you've released all references to it. It won't actually be deallocated until object B is deallocated or re-faulted, because it will still be retained by B.
One way of dealing with this (and other memory issues) is by calling refreshObject:mergeChanges: on the MOC for objects you aren't currently using, with the second argument set to NO. That re-faults the object, i.e. makes the object go back to the initial "fault" state, unloading its property values and relationships. With A and B from before, re-faulting B would release the relationship to A. Keep in mind this will lose any unsaved changes on B, so make sure you've saved first if necessary.
If your managed objects contain any kind of large binary data, try moving that data into a separate entity or out of Core Data altogether to avoid loading it into memory when it's not needed.
reset on the MOC is basically the nuclear option when it comes to Core Data memory management. It's extremely effective but as you've found can be very dangerous. It's best avoided unless you already aren't using any objects loaded from the MOC.

Attached objects vs Detached objects in entity framework

What are the benefits of using attached objects vs detached objects?
What I'm currently doing in my repository is manually detach my objects before i update or delete them. So if I'm updating or deleting, I do not do a round trip but I delete by ID. I think working with detached scenario works for me. Am I doing something wrong?
I'm working with an n-teir app that utilizes asp.net mvc and wcf.
Using attached objects will allow you to manipulate, track changes, do concurrency optimization. In most cases I use attached objects for updates or in a stateful application. This will also allow you to have lazy-loading and to benifit from the context cache. If you are using entity framework in a statefull manner, this is great because you can reduce the number of calls to the database when you require a single object from the context. Using the GetObjectByKey will query the context before making a query to the database. if the object was previously loaded, it will save you a round trip to the database.
Using detached objects are great! it allows for faster reads, simpler objects to materialize, a smaller memory footprint for the entity context. It is also best when sending data over the wire (wcf.. services). Anything out of scope, or even when you are converting the objects to domain objects. Since you do not require any tracking on the objects, this is a good optimization to start with. This can be acheived quickly using the NoTracking merge option on the entity set.
Detached objects will also greatly simplify working with EF in environments where you have many instances of your context. Simply attach the object before making changes and saving.
Note: using NoTracking will not allow you to use lazy-loading, change tracking, GetObjectByKey or any of the statefull functionalities of entity framework. Using NoTracking you will need to use eager loading ("Include()") to load related entities / navigation properties. EntityKeys will also not be loaded.
Edit:
Lazy-loading on detached entities, does not work because it does not have a context to refer to for its queries. The entity may also be missing the required proxies and entitykeys.
I would greatly suggest using eager loading. This may also be an optimisation in the end because it is hard to guage the impact of lazy-loading. Because it can produce situations where if you are iterating a collection, it will make a request to the database for each object in the collection. This can be quite problematic when you have large collections.
entity.User.Attach(model);
entity.ObjectStateManager.ChangeObjectState(model,System.Data.EntityState.Modified);
entity.SaveChanges();
return View(model);

Best way to 'dump' a Core Data stack?

My app needs to be able to disconnect from a server and connect to another one at whim, which necessitates dumping whatever persistent store we have. Issue here is that releasing the 'main' managed object context means whatever objects in it that I have laying around fault, which causes all sorts of unexpected little issues and crashes.
Is there a better way to 'reset' my stack/managed objects littered around the program than just calling release on everything in my Core Data stack?
You need to close down you Core Data stack from the top down.
Make sure that no managed objects are retained by any object other than the managed object context e.g. make sure the objects aren't held in an array owned by a UI controller.
Save the managed object context to clean up any loose ends.
Fully release the context and nil it. The context should never be retained by more than one object e.g the app delegate, anyway.
Send removePersistentStore:error: to the persistent store coordinator.
Use standard file operations to delete the actual store file.
Changing Core Data like this on the fly is difficult because Core Data isn't just a little database hung off the side of the app. It is intended to serve as the apps entire model layer. Since Apple is really into Model-View-Controller design, then the model is the actual core of the program (hence Core Data's name.) As such, you can't really turn it on and off the way you would a mere SQL database.
You might actually want to rethink your design so that you can change servers without having to shut down your entire data model. E.g. simply delete all managed objects associated with an unused server.
If you mean you want to fault all objects so they will be fetched again from your persistent store,
[managedObjectContext reset];

Resources