I have several cases where I have to update some object models, including the property that I use as a primary key.
For example :
Merge the primary key name (e.g. Georges, Anna...), and the familyName (e.g. Johnson, Smith...) property, and use that new merged name (e.g. Georges Johnson...) as a primary key.
Make the identifier primary key from type Int to type String
But of course the documentation clearly states that :
Once an object with a primary key is added to a Realm, the primary key cannot be changed
You can always remove old objects and create new ones, but this would add a lot of complexity to re-create the relationships.
And I'm pretty sure realm may not be happy with the identifier type change either way (judging by the thrown exceptions that I encountered).
So I was wondering if there was a simpler way to do so, or if I had to do a lot of manual grunt work to achieve my very simple goals.
Katsumi from Realm here. Realm supports primary key migration.
Primary keys can be changed only during migration. So you'd like to change the existing primary key values, you can write migration block, then you can assign new values for each new objects. The values must be unique of course.
let config = Realm.Configuration(schemaVersion: 1, migrationBlock: { (migration, schemaVersion) in
migration.enumerateObjects(ofType: "Person", { (oldObject, newObject) in
newObject!["key"] = ...
})
})
You can change primary key type as well.
In that case, you also need to write a migration block and assign new values. Because the primary key property is cleared when changing the type. Also, you can merge or split existing primary key property. You can add a new property, then specify it as a primary key, then you also should write migration block and assign new unique values as well.
However, the latest version of Realm (2.8.0 and 2.8.1) made unintentional bug that doesn't allow to modify primary key even during migration. So if you're urgent, you should use the previous version (2.7.x), if you are not urgent, please wait to be fixed the bug in next release.
Related
I have the following struct, with LinguisticMetadata being a relation:
metadataDB := &dbm.VideoMetadata{
ID: *imdbid,
ImdbID: *imdbid,
TmdbID: tmdbID,
IsSeries: input.Episode != nil,
ImdbRating: imdbRating,
Adult: extendedMetadata.Adult,
LinguisticMetadata: linguisticListDB, // LinguisticMetadata []*LinguisticMetadata `gorm:"not null"`
Subtitles: subtitlesDB, // Subtitles []*Subtitle
}
I want to create a new metadata, or update the existing one if it already exists. This is not an issue and can be achieved easily like so:
newMetadata := dbm.VideoMetadata{}
db.Where(dbm.VideoMetadata{ID: *imdbid}).Assign(metadataDB).FirstOrCreate(&newMetadata)
However, I also need to have the same behavior for its relations. The primary keys for LinguisticMetadata is the prefix of a country, eg: "en", "fr", "it"... So it is very likely that it already exists for the given metadata. Hence, if the primary keys of the relations already exist, the model should be updated (or replaced).
With the code shown above, I get the following error if the LinguisticMetadata primary key already exists:
pq: duplicate key value violates unique constraint "linguistic_metadata_pkey"
This does not make sense to me, because as stated here:
GORM will auto save associations and its reference when creating/updating a record. if association has a primary key, GORM will call Update to save it, otherwise it will be created.
I am trying to find a work-around for the EclipseLink bug bugs.eclipse.org/bugs/show_bug.cgi?id=344448.
The issue is that EclipseLink chooses a primary key made of entity ID + hashmap value ID for each entry of the HashMap. I would like to modify to have the primary key of entity ID + hashmap key ID instead. This is not only an issue with the primary key constraint but also with the SQL statements generated by EclipseLink, eg delete, update, etc...
So... I saw there is a way to customise this behaviour using a Customiser and by grabbing the ManyToManyMapping of the hashmap field and modifying whatever is needed. I can't find much documentation on this so I am sort of trying out things... but so far no success.
public class ConfigureValuesFilter implements DescriptorCustomizer {
public void customize(ClassDescriptor descriptor) throws Exception {
ManyToManyMapping mapping = (ManyToManyMapping) descriptor
.getMappingForAttributeName("values");
// various attempts
}
I tried setting the primary key with mapping.setTargetRelationKeyFieldName ("value_KEY"); and the setTargetKeyFieldNames (why does it need both?) but this resulted in an array index out of bound error with the table (from the key) I want to use not available in the descriptor, see below.
Exception Description: The table [CASEVALUE] is not present in this descriptor.
Descriptor: RelationalDescriptor(testdb.EULADocument --> [DatabaseTable(EULADOCUMENT)])
Then I tried changing the delete query statement with setDeleteSQLString, but I am stuck on how to pass the parameter values
mapping.setDeleteSQLString("DELETE FROM LICENSE_EULADOCUMENT WHERE ((values_KEY = #VALUES_KEY) AND (License_ID = #LICENSE_ID))");
says it could not find the VALUES_KEY so sets it to NULL...
What is the recommended way to modify the behaviour?
Lastest Realm Swift 1.0.1
I do follow this
composite primary key realm/swift
It's shows error following
How to i can write with Swift?
You will need to drop the lazy specifier from the variable declaration as how the error messages states such properties are not supported. You don't want to ignore the property as you want to use it as a primary key.
Beside that I would recommend to separate your integer components within your compound key. (e.g. "\(id)|\(tourId)") Otherwise you can end up having different objects with the same conflicting primary key. e.g. You could have objects with compoundKey="123" for the combination id=1 tourId=23, but also for id=12 tourId=3.
Within Realm how do you perform a Migration that adds the Primary Key function to a property, when using Swift?
This was previously answered for Realm Objective-C here: https://stackoverflow.com/a/29417579/599344
Essentially, if you're promoting a property to a primary key, and the property already has a unique value per object, you don't need to do anything special aside from running a normal migration.
If your new primary key property does have duplicate entries, then you'll need to change their values to something unique inside the migration block.
I'm getting more and more frustrated with EF...
I have a table called ExtendedField with:
Record
DocRef
DocType
Name
Record is the primary key
DocRef and DocType are foreign keys used to identify which Ticket they belong to
Name is the key used by the "definition" table to define what the field actually is
So basically I need 2 associations:
One between Ticket and ExtendedField
on ExtendedField.DocRef=ticket.record
and
ExtendedField.docType=HeaderDocType
One between Definition on
ExtendedField.Name=Definition.FieldName
Then I still need Record to be the primary key so I can directly access the fields.
As near as I can tell this is impossible to do in Entity Framework. For every association all the keys need to be mapped together, whereas I need two keys for one association, 1 key for another one and the actual primary key wouldn't be used in any associations.
It doesn't appear that you can define an association between fields that aren't entity keys either.
So is there any way to do this? Am I missing something?
It's a v1, bro. I myself have had some major pain with mapping of key constraints in EF. I hear that better things are coming in v2.