Recommended way to handle removing/renaming a realm model - react-native

I am using realm with the react-native app I am currently working on. The problem I am facing right now is that I need to rename or delete an old model and migrate the data to a new model.
Everything works nicely after I create new models, but when I look at Realm Browser to see new data, I can still see data with the old removed model.
I tried deleteAll with realm before inserting new data, and it doesn't seem to remove data with old model.
E.g. the app used to have a model names Car, but now I want to be more specific with Truck and Sedan, etc. So I create the new models, remove the old model Car, but I can still see data with Car after launch.
I am wondering if there is a way to delete the stale data. I tried doing migration, but since the schema does not have the old model, realm cannot refer to the stale data to delete them.

Realm.compact() removes the space left behind by deletions. Compacting works if there are no open Realm instances.
This will be added to the API in the version that comes after 1.10.3.

realm-js folks have exposed a method called Realm.deleteModel on Realm to delete model during migration. This should solve the problem of having stale data after migration when removing/renaming a model.
See https://github.com/realm/realm-js/issues/1268 for more detail

Related

Do I use Snapshot file, migration file or data annotations in my EF Core to update database?

I'm trying to understand the different types of migration paths we can choose when developing an ASP.NET Core 1.0 application with EF Core. When I created my first Core application I noticed it generated a ApplicationDbContextModelSnapshot class that uses a ModelBuilder to build the model.
Then I read that if I need to add a table to the database, I need to create the new model and run the command line to generate the migration file and update the database. Ok, I get it up to this point.
But when I do that, I notice that the ApplicationDbContextModelSnapshot class gets updated too.
1) Does that mean I cannot modify this ApplicationDbContextModelSnapshot class since it looks like it gets regenerated each time?
2) Should I use Data Annotations to build my model or should I use Fluent API which tells me to build my model in the ApplicationDbContext class? Huh? another file that builds the model?
I'm seeing three different ways of working with the database here, the snapshot class, data annotations, and fluent API. I'm confused because today, I made a mistake in my last migration file so I deleted the file, dropped the database and reran the database update.
But by doing that I got errors similar to:
The index 'IX_Transaction_GiftCardId' is dependent on column 'GiftCardId'.
ALTER TABLE ALTER COLUMN GiftCardId failed because one or more objects access this column.
So naturally I was wondering if I had to modify the ApplicationDbContextModelSnapshot class.
What is the path I should be taking when it comes to migrations or database updates because these three paths are confusing me.
I have run into this issue before when I create migrations, make model changes, create new migrations, and try to update the database. The root cause is when keys are being changed and relationships are not dropped and are not added back or do not exist.
You have two options
Easy Method
The easiest way is also the most destructive way and only possible in a dev environment.
Delete all migrations, drop the database, create new migrations and run 'update-database'.
Hard/Safest Method
This is the most time consuming method. I recommend do this in a local integration branch first, pushing it to a remote integration, and then production.
Open the migration file, ie 20160914173357_MyNewMigration.cs.
Drop all indexes in order
Drop/Add/Edit table schemas
Add all indexes back.
For either method, just be sure to test and test again.
Do not modify ApplicationDbContextModelSnapshot. It is a design-time artifact, and should only be modified in the case of a merge conflict.
To update the model, always use data annotations or the fluent API.
For more information on the EF Migrations workflow, see Code First Migrations. It's for EF6, but most of the information is still relevant.

Versioning and Serialization

So this is a question about Serialization and Versioning. I have a program that is a Music database that stores sheet music with Name, Composer, ...
I serialize each song to a hidden folder so that the user can reload the database at next launch.
Now, when I have to change something in the Song class all is fine if it is a compatible change. I had the idea that if I were to make an incompatible change, would I be able to create a second class with the same name 'Song' but a different VersionUID. Then when it reads the Songs, if the saved version doesn't match the latest version, it will go to a method that will read the Song into the old UID then go through a series of steps to convert it to the new Version. Is any of this possible?
I do know that you can have multiple methods with the same name but different parameters. Would this work with classes and VersionUID's or some other variable?
Thanks!
No it would not. Classes do not support a concept like "property overload" so a class with the same name is considered as the same class, even if it has different properties.
The "best" way for you would be a migration to a relational database in combination with EntityFramework6 (there is a SQLite adapter out there, so you don't need SQLServer).
With EF you can use migrations which enables you to change your model and migrate the data automatically. If done correctly you can change the model and no data loss occurs.

CoreData model update crashes

When I update my CoreData model, it crashes the app, So I have to delete the old app, and then reinstall. That's fine with me, but my question is: How do I tell my customer that they must delete the app before they reinstall? This seems too complicated...I am just adding 1 additonal field to a models and that's it.
Is there a better way to deal with this?
Thanks
You need to set up database migration... To upgrade a customer's existing data to the newest data model when they update. For some changes Core Data can do it for you. For others you'll have to write the migration code yourself.
Perhaps start here: https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/CoreDataVersioning/Articles/Introduction.html
Like #Nielsbot said, there's a migration system that Core Data uses.
You can create new versions of your model and select which one to use. There's a little bit of code to change in your AppDelegate method where the persistent store coordinator loads the model to tell it to load versions. I'd suggest you read Apple's documentation on how to implement this at: https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CoreDataVersioning/Articles/Introduction.html
If you're just adding one field to a table then you can create a new version of the database. Keep the current one unchanged.
In one of the menus there is a create new data version or something.
Make the changes in the new version.
There are numerous tutorials about how to do this.
If you release an update that crashes the app then apple won't approve it so you will have to so this anyway.

Saving core data model interrupted by power failure: Persistent store migration failed, missing mapping model

I've just opened the core data database of a customer who was using the app while he had a black out, so his mac turned off while saving the core data model.
The debugger says: Error: Persistent store migration failed, missing mapping model.
Is it because the model has been updated incorrectly and some parts are missing/invalid ?
Can I do something to restore this database ?
thanks
Apparently the model - the one described in the .xcdatamodel file - is no longer in sync with the actual data in the store. This happens when you make changes to your model: add entities, relations, change attributes etc.
To transfer the data from the store to the new model you use a Core Data mapping model (.xcmappingmodel file). This file describes the various modifications to your data model and allows Core Data to do a migration of the data from a previous version of the model to the new version. If this file is missing the data cannot be migrated/transferred to the new version of the model. Apparently, judging from the message received, the mapping model is not there.
The cause for this could be many, maybe because of a faulty build. Double check that the app has access to the mapping model and retry. If data is corrupted, you could try and use a backed up version of the data with a timestamp just before the black out and see if the migration will work from there.

Can I change a model from embedded to referenced without losing data?

I made a bad decision as I was designing a MongoDB database to embed a model rather than reference it in an associated model. Now I need to make the embedded model a referenced model, but there is already a healthy amount of data in the database (or document?).
I'm using Mongoid, so I reasoned I can just change embedded_in to referenced_in. Before I start, I figured I'd ask people who know better than I do. How can I transition the embedded data already in the database to the document for the associated model.
class Building
embeds_many :landlords
..
end
class Landlord
embedded_in :building
...
end
Short answer - Incrementally.
Create a copy of Landlord, name it Landlord2.
Make it referenced in Building.
Copy all data from Landlord to Landlord2.
Delete Landlord.
Rename Landlord2 to Landlord.
Users should not be able to CRUD Landlord during steps 3-5 (ideally). You still can get away with only locking CRUD on 4-5. Just make sure you make all updates that happened during copying, before removing Landlords.
Just chan ging the model like you have above will not work, the old data will still be in a different strucutre in the db.
Very similar the previous answer, one of the things I have done to do this migration before is to do it dynamically, while the system is running and being used by the users.
I had the data layer separated from the logic, so it let me add some preprocessors and inject code to do the following.
Lets say we start with the old datamodel, then release new code that does the following:
On every access to the document, you would have to check whether the embedded property exists, if it does, create a new entry associated as a reference and save to the database and delete the embedded property from the documents. Once this is done for a couple of days, a lot of my data got migrated and then I just had to run a similar script for everything that was not touched, made the job of migrating the data much easier and simpler and I did not have to run long running scripts or get the system offline to perform the conversion.
You may not ha ve that requirement, so Pick accordingly.