Versioning and Serialization - 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.

Related

Breeze and Point In Time Entities

We are creating a system that allows users to create and modify bills for their clients. The modifications need to be maintained as part of the bill for auditing purposes. It is to some extent a point in time architecture but we aren't tracking by time just by revision. This is a ASP.NET MVC 5, WebAPI2, EntityFramework 6, SQL Server app using Breeze on the client and the server.
I'm trying to figure how to get back the Breeze and our data model to work correctly. When we modify an entity we essentially keep the old row, make a copy of it with the modifications and update some entity state fields w/ date/time/revision number and so on. We can always get the most recent version of the entity based off of an entity ID and an EditState field where "1" is the most current.
I made a small sample app to work on getting Breeze working as part of the solution and to enable some nice SPA architecture and inline editing on the client and it all works... except that since our entity framework code automatically creates a new entity that contains the modifications, the SaveChanges response contains the original entity but not the new "updated" entity. Reloading the data on the client works but it would of course be dumb to do that outside of just hacking around for demo purposes.
So I made a new ContextProvider and inherited from EFContextProvider, overrode the AfterSaveEntities method and then things got a bit more complicated. Not all the entities have this "point in time" / revision functionality but most of them do. If they do I can as I said above get the latest version of that entity using its EntityId and EditState but I'm not seeing a straight forward way to get the new entity (pretty new to EF and very new to Breeze) so I'm hoping to find some pointers here.
Would this solution lie in Breeze or our DataContext? I could just do some reflection, get the type, query the updated entity and shove that into the saveMap. It seems like that might break down at some point (not sure how or when but seems sketchy). Is our architecture bad? Should we have gone the route of creating audit/log tables to store the modified values instead of keeping the datamodel somewhat smaller by keeping all of the revisions of the entities in their original tables but with the revision information and making the queries slightly more complicated? Am I just missing something in EF?
... and to head of the obvious response, I know we should have used a document database but that wasn't an option on this project. We are stuck in relational land.
I haven't tried this but another approach would be to simply change the EntityState of the incoming entity in the BeforeSaveEntities method from Modified to Added. You will probably need to also update some version field in this 'new' entity so that it doesn't have a primary key conflict with the original.
But... having built apps like this in the past, I really recommend another approach. Store your 'historical' entities of each type in a separate table. It can be exactly the same shape as the 'current' table. When you save you first copy the 'current' entity into the 'historical' table ( again with some version numbering or date schema for the primary key) and then just update your 'current' entity normally.
This might not give you the answer you expected, but here is an idea:
When saving an object, intercept save on server, you get an instance of object you need to modify, read object from database that has the same ID, put copy of that old object to legacy table in your database and continue with saving into main table. That way only latest revision stays in main table while legacy table would contain all previous versions.
So, all you would need to do is have two tables containing same objects:
public DbSet<MyClass> OriginalMyClasses{get;set;}
public DbSet<MyClass> LegacyMyClasses{get;set;}
override SaveChanges function and intercept when entry E state is Modified, read E type, get the original and legacy tables, read object O from Original with same ID as E, save O to Legacy table, and finally return base.SaveChanges(); (let it save as it is supposed to by default).

Cocoa Core Data and plain text file

I'm wrinting a very simple application which can read data from a specified file and populate the fetched data to a NSTableView. The file is a plain text file where each line represents an object (I need to parse the file). I want to use Core Data and my question is what is the Cocoa way to do that?
My first idea is to parse the file and create instances for the Entity which represents one line. I'm not sure that is it the best solution. And later I'll write out the changes to the file (after save? or automatically after a given amount of time?)
My configuration is Mountain Lion and the latest XCode.
A single entity with a number of attributes sounds good. If you had an attribute which holds a reasonable amount of data and was repeated on a number of 'rows' then it would be a candidate for another entity.
Yes, each instance of your entity would represent one row in your table.
Personally, I would either save on request by the user, or not have a save button and save each change. Your issue is the conversion between your in-memory store and on-disk store. Using a plain text file doesn't help (though, depending on the file format, it could be possible to edit individual lines in the file using NSFileHandle).
Generally it would still make more sense to use a better format like XML or JSON and then make use of a framework like RestKit which will do all of the parsing and mapping for you (after you specify the mapping configuration).
You can also use bindings to connect your data to your NSTableView. Another ref.

Core Data Alternatives on iOS

I've been developing several iOS applications using Core Data and it has been an excellent framework to work with. However, I've encountered an issue whereby we more or less have distributed objects (synced) across multiple platforms. A web/database server backend and mobile devices.
Although it hasn't been a problem until now, the static nature of the data model used by Core Data has me a little stuck. Basically what is being requested is a dynamic forms system whereby forms can be created on a server and propagated to the devices. I'm aware of the technique for performing this with a set number of tables with something like:
Forms table
Fields table
Instance of Forms table
Instance Values table
and just linking everything together. What I'm wondering however is if there is an alternative system to Core Data (something above talking to an SQLite database directly) that will allow for a more dynamic object graph. Even a standard ORM would be good if there are options for modifying the schema at runtime. The main reason I want to go down this route is for performance in the sense that I don't want the instance values table exploding with entries (on the local device or server).
My other option is to have the static schema (object-graph) on the iOS devices but have a conversion layer on the server's side which fetches the correct object, populates the properties and saves it to the correct table. Then when the devices comes to sync, it does the reverse and breaks it down into instances. While this saves the server from having a bloated instance value table, it could still be a problem on the device.
Any suggestions are appreciated.
Using specific tables/entities for forms and fields, and entities for instances of each, is probably what I would recommend. Trying to manipulate the ORM schema on the fly if it's going to be happening frequently doesn't seem like a good idea in general.
However, if the schema is only going to change infrequently, you can probably do it with Core Data. You can programatically create and/or manipulate the NSManagedObjectModel prior to creating a NSManagedObjectContext. You can also create migration logic so data stored in an old model can be preserved when you update the model and need to recreate the context and stores.
These other SO posts may be helpful:
Customize core data model at runtime?
Handling Core Data Model Changes
You need to think carefully about what you are actually modeling.
Are you modeling: (1) the actual "forms" i.e. UI elements, (2) data that might be presented in any number of UI versions e.g. firstName or (3) both?
A data model designed to model forms would have entities like:
Form{
name:string
fields<-->Field.form
}
Field{
width:number
height:number
xPos:number
yPos:number
label:sting
nextTab<-->Field.priorTab
priorTab<-->Field.nextTab
form<<-->Form.fields
}
You would use this to store data about form as displayed in the user interface. Then you would have a separate entities and probably a separate model to store the actual data that would populate the UI elements that are configured by the first data model.
You can use Core Data to modeling anything you just need to know what you are really modeling.

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.

Storing default instances of an NSManagedObject in every new file

I have a core data document based application. Part of my model works by having a DeviceType table, and a Devices table with a relation between them. I would like my application to be able to store the list of DeviceTypes separately from each file, and possibly be able to sync that to a server later.
What would be the best way to accomplish this?
Thanks,
Gabe
You're using a lot of database terminology with Core Data. You should break that habit as soon as possible (the reasons why are given in the introductory paragraphs to the Core Data Programming Guide).
I assume your "usually-static" device list is something you want to be able to update as new devices come out? I would actually recommend just storing the list as a PLIST resource in your app bundle and pushing an update to the app when new devices come out (for simplicity). Using a dictionary-based PLIST, your keys can be device IDs and that key can be a simple string attribute of your managed objects. It's perfectly reasonable to look things up outside your Core Data model based on some ID.
If you must update, I'd still include the "default" list with the app (see above) but if a ".devicelist" (or whatever) file is present in the documents folder, use that instead. That way you can periodically check for an updated list and download it to the docs folder if it differs.
If I've misunderstood you, I encourage you to clarify either by editing your question or posting comments.