Core Data Entity Global Data - macos

I have a Core Data entity that is used to store earthquake reports. I would like to store a bit of global data to keep track of when the data was last updated.
The date should be a single date common to all entity objects in the store.
Can I use the Entity userInfo for this? I can't determine if this is read-only or if it can be altered at runtime.
Is there a better way? I don't want to store it in UserDefaults because if the sql files are deleted I want the "date updated" data to go away as well.

Persistent stores can have metadata about the store in addition to the actual data. That would be a good place for this. Metadata is part of the NSPersistentStore, so you have to reach down into the NSPersistentContainer to get it and change it. Something like this
guard let persistentStore = persistentContainer.persistentStoreCoordinator.persistentStores.first else {
return
}
var metadata = persistentContainer.persistentStoreCoordinator.metadata(for: persistentStore)
metadata["updated"] = Date()
persistentContainer.persistentStoreCoordinator.setMetadata(metadata, for: persistentStore)
self.saveContext()
The last line is there because metadata doesn't get saved until you save changes, even though it's metadata instead of actual data.
It's best to read the existing metadata first because Core Data puts some of its own metadata in there. You probably wouldn't be able to corrupt that, but make sure by reading it first and leaving the existing values alone.

Related

Saving an object if not exists without using ObjectId (JS)

I'm trying to find a way to save a new object if one like it doesn't already exist with a specified custom ID.
I basically need to refresh a whole bunch of data every day but each item has its own ID set somewhere else (so not a parse objectId). I therefore can't use something like the standard save function as it'll just make a new record every time.
I've thought of trying to set the objectId of an object when its first created in the DB but I can't seem to do that... (Half expected this).
I've also thought of doing the obvious - checking if an object exists using a normal query but with a few thousand objects to compare, this will be very inefficient.
Any suggestions?
Maybe there is a save function or variation where its kind of "save or create depending if an object exists with this value in this field" :)
Thank you!
PS. I'm writing this within a Cloud Job - so JavaScript

How to store filtered data?

I'm building an API which handles purely the storage of data.
Let's imagine inside Redis I've remembered the key foo:123 for 20 minutes, which holds an Eloquent Collection since I'm using the collection later on rather than returning the raw json.
As example the foo collection could look like
[
{
"name":"Doe",
"first_name":"John",
"age":42,
"favorite_color":"red"
},
{
"name":"Example",
"first_name":"Eric",
"age":37,
"favorite_color":"black"
},
....
]
How would I store a new collection, which has the same structure but entries having black as favorite_color? Would I have to store something like foo:123:black? Do I store the full collection and filter it down manually? Or is this done completely different when using Redis?
Q: How would I store a new collection, which has the same structure but entries having black as favorite_color?
Why not just map over the collection and update the favorite_color to black? https://laravel.com/docs/5.4/collections#method-map. Then store it however you want, either overwrite the old data or create new data.
Q: Would I have to store something like foo:123:black?
It's not clear to me what you're asking for here. I'm not sure we can give you any answers on how you choose to store it or the naming convention.
Q: Do I store the full collection and filter it down manually?
This is something you would need to decide based on your app requirements. It should be possible to serialize a collection and store it, but it may be a huge waste of resources if you're doing this with a bunch of different collections that have minor differences.

How to fetch data in tabular form in _new page

I'm creating a project in ruby on rails. Is it possible to add data just like normal form and save them in database in show page? Is it possible to add data in tabular form and let the user save the data in batch (i.e. 5-6 record at a time) for the same employee? If so, then how can I achieve this functionality?
You can read all needed information from file and parse it into the array of objects, and then use https://github.com/zdennis/activerecord-import gem for insert it in db (for production).
also, you may look into db/seeds.rb file for adding new data in develop.

Entity Framework and caching - Changes are tracking back to cache

I have some data being pulled in from an Entity model. This contains attributes of items, let's say car parts with max-speed, weight and size. Since there are a lot of parts and the base attributes never change, I've cached all the records.
Depending on the car these parts are used in, these attributes might now be changed, so I setup a new car, copy the values from the cached item "Engine" to the new car object and then add "TurboCharger", which boosts max speed, weight and size of the Engine.
The problem I'm running into is that it seems that the Entity model is still tracking the context back to the cached data. So when weight is increased by the local method, it increases it for all users. I tried adding "MergeOption.NoTracking" to my context as this is supposed to remove all entity tracking, but it still seems to be tracking back. If I turn off the cache, it works fine as it pulls fresh values from the database each time.
If I want to copy a record from my entity model, is there a way I can say "Copy the object but treat it as a standard object with no history of coming from entity" so that once my car has the attributes from an item, it is just a flattened object?
Cheers!
Im not too sure about MergeOption.NoTracking on the whole context and exactly what that does but what you can do as an alternative is to add .AsNoTracking() into your query from the database. This will definitely return a detached object.
Take a look here for some details on AsNoTracking usage : http://blog.staticvoid.co.nz/2012/04/entity-framework-and-asnotracking.html.
The other thing is to make sure you enumerate your collection before you insert to the cache to ensure that you arent acting within the queriable, ie use .ToArray().
The other option is to manually detach the object from the context (using Detach(T entity)).

Accessing properties of Core Data objects via bindings from non-Core Data objects

I have a set of data created by another app and stored in XML format on disk. Since this data is managed by this other app, I don't want to bother with loading this data into a Core Data store for two reasons: 1) it would be redundant storage of the same data, and 2) I would have to constantly update my own Core Data store to match updates in the XML file produced by the other app.
However, I have data created in my own app that needs to be associated with the data from the XML from the other app, and I want to save the data created in my own app to disk.
To accomplish this, the XML data from the other app has persistent, unique IDs associated with each object stored in the XML file. I store these unique IDs in my own Core Data store. Upon every launch of my app, I load the XML data created by the other app, and then I can access the corresponding data in my own app via Core Data by issuing a fetch request for managed objects matching the unique ID.
OtherAppObjects represents items loaded from the XML data. They have their own unique properties in addition to the uniqueID. These OtherAppObjects are controlled by an NSArrayController. Then I have MyManagedObjects which are loaded from the Core Data store, and have distinct unique properties in addition to a uniqueID.
I have a table view which needs to display properties from both the OtherAppObjects as well as the MyManagedObjects, so I want to be able to access and set properties of the MyManagedObjects via bindings from the OtherAppObjects. Thus, I figured that I could create a correspondingMyManagedObject property of the OtherAppObjects, and then I'd be able to access the Core Data properties of the MyManagedObject via bindings.
For example, if I wanted to display property "foo" of the OtherAppObjects, and "bar" of the MyManagedObjects in the table view, I could simply bind one table column to the NSArrayController with a model key path of "foo", and bind the second table column to the model key path of "correspondingMyManagedObject.bar".
This works when not dealing with multiple threads, or when passing around a single managed object context. But since that's "strongly discouraged", I wanted to try to do this the right way by passing around a single persistent store coordinator, but creating separate managed object contexts.
However, this breaks down. The problem is that when the table view attempts to access the bar property, it needs to first access the correspondingMyManagedObject property. So, the OtherAppObject dutifully creates a new managed object context and a corresponding fetch request with the appropriate uniqueID and returns the managed object. But in doing so, it releases the managed object context and now the managed object is no longer valid, so the table view can't access the bar property!
I see only two ways around this, and I wanted to verify that there isn't another easier way to do this:
Load the objects from the XML data into my own Core Data store. In essence, create ManagedOtherAppObjects from the OtherAppObjects, with a relationship to the MyManagedObjects, and then accessing via bindings will be peachy. However, this means there's redundant storage of the same data on disk, and I'll have to recreate the ManagedOtherAppObjects every single time I launch the app (because the XML file is updated fairly frequently).
Create custom setters/getters on the OtherAppObject class. So, for example, I'd create -(NSValue *)bar and -(void)setBar:(NSValue *)newValue methods in OtherAppObject. Then, instead of binding the table view column to the key value path "correspondingMyManagedObject.bar" of OtherAppObjects, I'd just bind it to the key path "bar" of OtherAppObjects. These methods would be able to fetch the corresponding MyManagedObject and retrieve or set the value within the managed object context, and then return the correct value.
This second method isn't particularly appealing because I'd have to create two custom methods for every single property of MyManagedObject (and for properties of other managed objects for which MyManagedObject has a relationship).
I suppose I could create the generalized methods -(NSValue *)retrieveCoreDataPropertyUsingKeyPath:(NSString *)keyPath and -(void)setCoreDataProperty:(NSValue *)newValue usingKeyPath:(NSString *)keyPath , but I'd still have to create shell setters/getters for each individual property.
[UPDATE: Hmm, maybe I could just override valueForKeyPath: and setValue:forKeyPath:, and then everything would work OK?]
Is this correct, or am I missing something?
One variation on option #1 that could be worth a try would be to set things up so that you have a single persistent store coordinator that splits the objects between two separate persistent stores. You would keep MyManagedObjects (MMO) the same, being stored separately on disk, but then the OtherAppObjects (OAO) could either be backed by some temporary store on disk (e.g. in ~/Library/Caches or something) or just by an in-memory store.
Upon launch, you would create your PSC and add the store containing the MMOs. You would then add a second store to the PSC (using -[NSPersistentStoreCoordinator addPersistentStoreWithType:configuration:URL:options:error:]), read in the XML file and create all the OAOs, and associate those objects with that store using -[NSManagedObjectContext assignObject:toPersistentStore:].
Core Data doesn't allow directly modeling relationships between objects in different stores, but you could still do the lookup via unique ID like you're doing now to associate a MMO with an OAO. The difference would be that the OAO could simply use its own managed object context to fetch the MMO, so you would be sure that the MMO would stick around at least as long as the OAO.
Then, when you quit the app, you'd either delete the temporary store in ~/Library/Caches, or if using an in-memory store, just let it disappear into the ether, leaving the other store with the MMOs intact.

Resources