What's the point of setRetainsRegisteredObjects:? - iphone

Why would I want to set that to YES? What difference would that make? Must I worry about this?

setRetainsRegisteredObjects: to YES makes your context maintain a strong reference to managed objects that it would otherwise maintain a weak relationship with. When you perform a fetch request, the objects returned have a weak reference (by default) to the respective managed object context. Only when an object is modified (added, changed, deleted) does the managed object context (MOC) maintain a strong relationship to the object.
Setting setRetainsRegisteredObjects: to YES ensures that strong pointers will be maintained between all fetched objects.
I don't know what #TechZen is talking about - this can be the cause for a sneaky bug if you're not careful. It's a useful method to invoke on the MOC when you find yourself in a situation where this would be useful.

Worry? I don't know, are you interested in wasting time?
You only fiddle with this particular context attribute when you want to do custom memory management within Core Data (which you almost never do.) I had to go look this up just to remember what it was because I haven't used it in years.
The rule of thumb with Core Data is that if you have an attribute with a default value then you use the default value in the vast majority of cases. That's why its the default.
Unless you see a context attribute changed in virtually every example i.e. the store name, then it is not necessary to change it in 90% of the uses. It is certainly not necessary for a novice to try and change it.
Core Data is intended to be relatively simple once you under it abstractly. Using binding, it is possible to use Core Data on the Mac without writing any code at all. Everything just works with the default configuration.

Related

Is it a bad practice to open a new context or send one as a parameter into sub-methods?

A colleague asked for my opinion regarding the following setup. It's based on a declaration of a context in a method and then providing it into the called submethods. Schematically, it looks like so.
public void SuperMethod()
{
using(Context context = new Context())
{
...
SetMethod(context, ...);
...
GetMethodDuo(context, ...);
...
}
}
public void SetMethod(Context context, ...) { ... }
public Some GetMethod(Context context, ...) { ... }
I advised him against it, motivating my answer by the idea of opening/closing access to the database as near the actual operations as possible. But now that I think about it, I'm uncertain if that was the best advice in any circumstances.
Question 1: Was the suggestion of mine correct in a general case or should I consider altering it?
I also noticed that the super-method calling the sub-methods used the context itself. My suggestion was to move the part that talked to the database in a new sub-method, hence freeing the super-method from any references to the context. I felt that it made sense to make the super-method a controller, while performing all the database related operations in the workers.
Question 2: Does it make sense to have a controlling method that calls a (possibly large) number of sub-methods carrying the actual work?
Please note that both questions are related to the usage of the context while working with Entity Framework and not a general class structure.
IMO, the context should be opened and disposed with every unit of work (so for example, within a simple function) - which doesn't mean you shouldn't pass your context to underlying functions. This can be exactly what you want, especially considering connection pooling and context entry lifetime.
This has a few pretty simple reasons:
It's pretty cheap to open a new context, it will take almost no time relatively to the main performance issues in EF like materializing values (DataSet to object and vice versa) and creating the queries - and those two have to be done with an already open context as well.
One main reason against opening and disposing a context every time is the opening/disposing of connections (some DBMS, I know particularly of SQL CE, have incredible problems with the creation of connections to certain databases - and EF will create a new connection based on the provided connection string whenever it needs one). However, you can easily surpass this, by keeping a connection open (or letting it timeout isn't too bad most of the time either) and pass it to your context upon creating, using the DbContext(Connection, bool) overload with ContextOwnsConnection=false.
When you keep the context open over the whole lifetime, you can't possibly know which objects are already in the change tracker, materialized or there in another form, and which aren't. For me, this was a problem when rewriting the BL of my project. I tried to modify an object, which I added earlier. It was in the context (unchanged) but not in the change tracker, I couldn't set its state, because it wasn't in the change tracker. And I couldn't attach it again, because it was already in the context. This kind of behavior will be pretty hard to control.
Another form of this is as follows. Whenever a new object enters the context, EF will try to set the navigation properties of these regarding the other objects in the context. This is called relationship fixup and is one of the main reasons Include() is working so well. This means that most of the time, you'll have a huge object tree in your context. Then, upon adding/deleting it (or whatever else operation) EF will try to carry out this to the whole tree (well... sometimes ;) ), which can cause a lot of trouble, especially when trying to add a new entry with FK to already existing items.
A database context is, like already mentioned, basically an object tree, which can be, depending on its lifetime, gigantic. And here, EF has to do a few things, like... Checking if an item is already there, because of obvious reasons... In best case complexity O(n*log(n)+m), where m is the number of object types and n the number of objects of this type in the context. ...Checking if an object has been modified since retrieval - well, you can imagine, since EF has to do this for every single object in every single call, this can slow things down pretty far.
A bit corresponding to the last issue. What do you really want, when calling SaveChanges()? Most likely, you want to be able to tell: "ok, these are the actions I did, so EF should now issue these and these calls to the db", right? Well... But, since EF has been tracking the entities, and maybe you modified some values, or another thread did something there and there... How can you be sure, these are the only things SaveChanges() will do? How can you be sure that over the whole lifetime of the context, there's nothing fishy in your database then (which will cancel the transaction, which can be pretty big)?
But yeah, of course, there are a few issues, where you need to keep the context open (well, you don't need to - you could just pass it). For me, this was mostly in a few cases where FK correction was hard to maintain (but still within one function, while sometimes within one function I just had to dispose and re-create the context for the sake of simplicity) and whenever you call sub-functions from multiple places in your code - I had the issue that I had a context open within a calling function, which called another function, which still needed the context. Usually, that's not a problem but my connection handling is kind of... advanced. That led to performance loss, I dealt with this by passing the already open context through an optional additional context parameter to the sub-function - just like what you already mentioned, however it shouldn't really be necessary.
For additional reference, here are some links that might be helpful in this regard. One's straight from MSDN and the other from a blog.
As #DevilSuichiro mentioned the DbContext is meant as a Unit of Work container. By default DbContext stores all loaded objects in the memory and track their changes. When the SaveChanges method is called all changes are sent to a DB in the single transaction.
So if your SuperMethod handles some kind of a logical unit of work (e.g. a HTTP request in a web application) I would instantiate the context only once and pass it as a parameter to submethods.
Regarding your second question - if you instantiate the context only once, it's IMO better to have more methods that are simple, easier to maintain and have meaningful names. If you want to create a new instance of the context in every submethod, it depends on what "possibly large" number means :-)

Simple memory management with core data and ARC

I am still getting used to some of the details of memory management in objective-c, despite the fact that ARC simplifies things significantly. Here is a line of code:
[song addEntriesObject:self.entry];
where song is a managed object that I access by executing a fetch request on my managed object context, and self.entry refers to an instance variable that is passed into this class upon initialization, and is also a managed object (i.e. it's a core data entity - hope I'm using that terminology properly).
My question is simply whether this will cause any problems in memory management, i.e. whether assigning self.entry to a managed object will prevent that instance variable from being released because it is being retained by core data, or something along those lines. Would this create any problems, or does core data not maintain pointers to objects in the same way? Or am I just completely on the wrong track with my thought process here?
Any thoughts on the subject would be much appreciated.
cowfaboo,
Core Data objects are NSObjects and hence behave identically. In other words, nothing changes with respect to memory management. In your example, self.entry is retained by both your instance and by song.
Independent of ARC, Core Data items can retain large object graphs. These may need to be pruned. The -refreshObject:mergeChanges: method is used to do this. To save yourself some pain, you should always use -save: before trimming your graph.
Andrew

validation of persistent ignorant domain objects

I want to know how to check if Domain Object is in right state while saving it.
If Object has persistent information - it is clear as for instance I can check Order's amount in its Save method. However persistent ignorant objects don't have Save method. They just have data and behavior. Should I rely on developers' accuracy or I need to check all entities graphs somehow before saving it in database?
Perhaps I'm not understanding you right.
I'm not sure how you get an "ignorant" object. That seems to run against the core tenet of encapsulation. The only way to modify an object's state should be through its interface. It's the interface's responsibility to ensure any updates to state are valid. So, to your example, you shouldn't need to check the amount in the save() operation (assuming here "save" means persist). It should be updated as a consequence of e.g. calling addProduct() (or something similar - i.e. adding item to order updates amount).
Whether an object is persistent or transitory is irrelevant - it should always encapsulate state update through its interface.
Hope that helps - apologies if I've misunderstood.

NSKeyedArchiver encode only part of an array

I have a list of objects that can sometimes change, and I want to keep a persistent cache on the device whenever the app is closed or move to the background.
Most of the objects in the list will not change, so i was wondering what is the best way to save the list. I have two major options i think about:
Using NSKeyedArchiver / unArchiver - This is the most convenient method, because the objects i'm serializing hold other custom objects, so this way i can just write a custom encode method for each of them. The major problem is that i didn't find on Google how to serialize only the changed objects, and serializing the entire list every time seems very wasteful.
Using SQLite - this is what i'm currently using, and the worst problem here is that adding \ changing properties of the objects is very complicated, and much less elegant.
Is there any way that i can enjoy the convenience of NSKeyedArchiver but only serialize the changed objects?
Like Adam Ko I would suggest using Core Data:
This kind of problem is what it's really good at, after all!
If your cache items are independent from each other, this could be achieved by simply wrapping your cache-items by a thin layer of NSManagedObject (i.e. you could benefit from Core Data with only minor changes to your app).
This wrapper entity could store an archived version of a cache item in an attribute of type NSBinaryDataAttributeType and provide access to the unarchived object through a transient property.
See Non-Standard Persistent Attributes for an example.

Create a Core Date Entity Instance But not want it to be stored(non-persistent)

Sometimes I need instantiate CoreDateEntity to store some infomations for temporarily using.
But I needn't it be stored into DB.
currently I created a similar class which have same structures as the CoreDateEntity does.
It works well but I have to do many datas transfer between Two models.
Is there any better way to handle this?
Thanks for all the replies. but you guys just give me half answer of this. consider about this, I need place some entity without MOC into current database pool, how could I do this? I already checked the documents of CoreData, seems I didn't find API to transfer one entity from MOC to another MOC(manage object context).
According to Apple docs you can initialize a managed object without context if you specify nil as context.
- (id)initWithEntity:(NSEntityDescription *)entity insertIntoManagedObjectContext:(NSManagedObjectContext *)context
You can assign entities to different stores when you set up the data model. Have one store be the persistent store and the other an in-memory store. You can't form relationships across stores but it sounds like you don't need that.
To assign a configuration, hit the configuration tab (the one with the wrench icon) in the entity detail (where you give it its name, class and parent). When you create the persistent store, add the configuration name to the options dictionary.
Update:
I think you maybe overcomplicating things. It sounds like you have some managed objects that will be temporary and some that will persisted but sometimes you may want to save the temporary objects. I don't think you should bother trying to separate out the "temporary" objects. Doing so just adds complexity without any performance benefit. Instead, just use ordinary persisted objects and then delete the ones you don't want.
Always try the simplest solution first.
Use two different managed object context's and only save the objects from one context. Be careful not to set relationships between objects of two different context's - this doesn't work.